diff --git a/bin/now-alias.js b/bin/now-alias.js index 498a6ed..c187c18 100755 --- a/bin/now-alias.js +++ b/bin/now-alias.js @@ -32,7 +32,7 @@ const argv = minimist(process.argv.slice(2), { const subcommand = argv._[0]; -// options +// Options const help = () => { console.log( ` @@ -92,7 +92,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; @@ -211,7 +211,7 @@ async function run(token) { ); return [ '', - // we default to `''` because some early aliases didn't + // We default to `''` because some early aliases didn't // have an uid associated _alias.uid === null ? '' : _alias.uid, _sourceUrl, @@ -342,7 +342,9 @@ async function confirmDeploymentRemoval(alias, _alias) { const msg = '> The following alias will be removed permanently\n' + ` ${tbl} \nAre you sure?`; - return await promptBool(msg); + + const prompted = await promptBool(msg); + return prompted; } function findAlias(alias, list) { @@ -366,7 +368,7 @@ function findAlias(alias, list) { return true; } - // match prefix + // Match prefix if (`${val}.now.sh` === d.alias) { if (debug) { console.log(`> [debug] matched alias ${d.uid} by url ${d.host}`); diff --git a/bin/now-billing-add.js b/bin/now-billing-add.js index c17b8ee..d14b54f 100644 --- a/bin/now-billing-add.js +++ b/bin/now-billing-add.js @@ -117,6 +117,7 @@ module.exports = function(creditCards) { } else if (typeof piece === 'object') { let result; try { + /* eslint-disable no-await-in-loop */ result = await textInput({ label: '- ' + piece.label, initialValue: piece.initialValue || piece.value, @@ -126,7 +127,9 @@ module.exports = function(creditCards) { validateValue: piece.validateValue, autoComplete: piece.autoComplete }); + piece.value = result; + if (key === 'cardNumber') { let brand = cardBrands[ccValidator.determineCardType(result)]; piece.brand = brand; @@ -178,7 +181,7 @@ module.exports = function(creditCards) { } } } - console.log(''); // new line + console.log(''); // New line const stopSpinner = wait('Saving card'); try { diff --git a/bin/now-billing.js b/bin/now-billing.js index 8b7c148..30721ad 100644 --- a/bin/now-billing.js +++ b/bin/now-billing.js @@ -69,7 +69,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; @@ -78,7 +78,7 @@ if (argv.config) { } const exit = code => { - // we give stdout some time to flush out + // We give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 diff --git a/bin/now-certs.js b/bin/now-certs.js index f80c5c7..939bd80 100755 --- a/bin/now-certs.js +++ b/bin/now-certs.js @@ -32,7 +32,7 @@ const argv = minimist(process.argv.slice(2), { const subcommand = argv._[0]; -// options +// Options const help = () => { console.log( ` @@ -73,7 +73,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; diff --git a/bin/now-deploy.js b/bin/now-deploy.js index 7b6a18a..cac09b0 100755 --- a/bin/now-deploy.js +++ b/bin/now-deploy.js @@ -146,7 +146,7 @@ const help = () => { let path = argv._[0]; if (path) { - // if path is relative: resolve + // If path is relative: resolve // if path is absolute: clear up strange `/` etc path = resolve(process.cwd(), path); } else { @@ -156,7 +156,7 @@ if (path) { // If the current deployment is a repo const gitRepo = {}; -// options +// Options let forceNew = argv.force; const debug = argv.debug; const clipboard = !argv['no-clipboard']; @@ -483,7 +483,7 @@ async function sync(token) { console.log( `> Reading ${chalk.bold(`"${chalk.bold(key)}"`)} from your env (as no value was specified)` ); - // escape value if it begins with @ + // Escape value if it begins with @ val = process.env[key].replace(/^@/, '\\@'); } else { error( @@ -585,10 +585,10 @@ async function sync(token) { console.log('> Initializing…'); } - // close http2 agent + // Close http2 agent now.close(); - // show build logs + // Show build logs printLogs(now.host, token); }; @@ -624,16 +624,16 @@ async function sync(token) { console.log(`> Initializing…`); } - // close http2 agent + // Close http2 agent now.close(); - // show build logs + // Show build logs printLogs(now.host, token); } } function printLogs(host, token) { - // log build + // Log build const logger = new Logger(host, { debug, quiet }); logger.on('error', async err => { @@ -663,9 +663,13 @@ function printLogs(host, token) { const aliasList = autoAliases.filter(item => item !== ''); if (aliasList.length > 0) { + const assignments = []; + for (const alias of aliasList) { - await assignAlias(alias, token, host, apiUrl, debug); + assignments.push(assignAlias(alias, token, host, apiUrl, debug)); } + + await Promise.all(assignments); } else { await reAlias(token, host, help, exit, apiUrl, debug); } diff --git a/bin/now-dns.js b/bin/now-dns.js index c888c8d..8fed33a 100755 --- a/bin/now-dns.js +++ b/bin/now-dns.js @@ -29,7 +29,7 @@ const argv = minimist(process.argv.slice(2), { const subcommand = argv._[0]; -// options +// Options const help = () => { console.log( ` @@ -65,7 +65,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; if (argv.config) { diff --git a/bin/now-domains.js b/bin/now-domains.js index 00eea18..ae055bb 100755 --- a/bin/now-domains.js +++ b/bin/now-domains.js @@ -31,7 +31,7 @@ const argv = minimist(process.argv.slice(2), { const subcommand = argv._[0]; -// options +// Options const help = () => { console.log( ` @@ -99,7 +99,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; @@ -319,7 +319,7 @@ function findDomain(val, list) { return true; } - // match prefix + // Match prefix if (d.name === toHost(val)) { if (debug) { console.log(`> [debug] matched domain ${d.uid} by name ${d.name}`); diff --git a/bin/now-list.js b/bin/now-list.js index 3ed735c..ad72dc2 100755 --- a/bin/now-list.js +++ b/bin/now-list.js @@ -61,7 +61,7 @@ if (argv.help) { const app = argv._[0]; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; diff --git a/bin/now-open.js b/bin/now-open.js index 5935ad7..545ed72 100644 --- a/bin/now-open.js +++ b/bin/now-open.js @@ -53,7 +53,7 @@ if (argv.help) { const app = argv._[0]; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; diff --git a/bin/now-remove.js b/bin/now-remove.js index 6d44821..aa61bf1 100755 --- a/bin/now-remove.js +++ b/bin/now-remove.js @@ -28,7 +28,7 @@ const argv = minimist(process.argv.slice(2), { const ids = argv._; -// options +// Options const help = () => { console.log( ` @@ -66,7 +66,7 @@ if (argv.help || ids.length === 0) { process.exit(0); } -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; const hard = argv.hard || false; diff --git a/bin/now-secrets.js b/bin/now-secrets.js index 04b5fe1..3d47f4c 100755 --- a/bin/now-secrets.js +++ b/bin/now-secrets.js @@ -29,7 +29,7 @@ const argv = minimist(process.argv.slice(2), { const subcommand = argv._[0]; -// options +// Options const help = () => { console.log( ` @@ -74,7 +74,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; diff --git a/bin/now-upgrade.js b/bin/now-upgrade.js index 0c88624..517800b 100644 --- a/bin/now-upgrade.js +++ b/bin/now-upgrade.js @@ -58,7 +58,7 @@ const help = () => { ); }; -// options +// Options const debug = argv.debug; const apiUrl = argv.url || 'https://api.zeit.co'; @@ -67,7 +67,7 @@ if (argv.config) { } const exit = code => { - // we give stdout some time to flush out + // We give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 diff --git a/lib/agent.js b/lib/agent.js index 6cd0de2..1678ed9 100644 --- a/lib/agent.js +++ b/lib/agent.js @@ -30,11 +30,11 @@ module.exports = class Agent { _initAgent() { const module = this._protocol === 'https:' ? https : http; - const agent = (this._agent = new module.Agent({ + this._agent = new module.Agent({ keepAlive: true, keepAliveMsecs: 10000, maxSockets: 8 - }).on('error', err => this._onError(err, agent))); + }).on('error', err => this._onError(err, this._agent)); } _onError(err, agent) { diff --git a/lib/alias.js b/lib/alias.js index bd67e15..63b37a7 100644 --- a/lib/alias.js +++ b/lib/alias.js @@ -82,7 +82,7 @@ module.exports = class Alias extends Now { return true; } - // match prefix + // Match prefix if (`${val}.now.sh` === d.url) { if (this._debug) { console.log(`> [debug] matched deployment ${d.uid} by url ${d.url}`); @@ -99,8 +99,9 @@ module.exports = class Alias extends Now { async updatePathBasedroutes(alias, rules) { alias = await this.maybeSetUpDomain(alias); + const upsert = await this.upsertPathAlias(alias, rules); - return await this.upsertPathAlias(alias, rules); + return upsert; } async upsertPathAlias(alias, rules) { @@ -130,7 +131,7 @@ module.exports = class Alias extends Now { return body; } - // no retry on authorization problems + // No retry on authorization problems if (res.status === 403) { const code = body.error.code; @@ -161,7 +162,7 @@ module.exports = class Alias extends Now { return bail(new Error('Authorization error')); } - // all other errors + // All other errors if (body.error) { const code = body.error.code; @@ -173,13 +174,13 @@ module.exports = class Alias extends Now { try { await this.createCert(alias); } catch (err) { - // we bail to avoid retrying the whole process + // We bail to avoid retrying the whole process // of aliasing which would involve too many // retries on certificate provisioning return bail(err); } - // try again, but now having provisioned the certificate + // Try again, but now having provisioned the certificate return this.upsertPathAlias(alias, rules); } @@ -199,7 +200,7 @@ module.exports = class Alias extends Now { return bail(new Error(body.error.message)); } - // the two expected succesful cods are 200 and 304 + // The two expected succesful cods are 200 and 304 if (res.status !== 200 && res.status !== 304) { throw new Error('Unhandled error'); } @@ -307,7 +308,7 @@ module.exports = class Alias extends Now { return { uid: body.error.uid }; } - // no retry on authorization problems + // No retry on authorization problems if (res.status === 403) { const code = body.error.code; @@ -338,7 +339,7 @@ module.exports = class Alias extends Now { return bail(new Error('Authorization error')); } - // all other errors + // All other errors if (body.error) { const code = body.error.code; @@ -354,13 +355,13 @@ module.exports = class Alias extends Now { try { await this.createCert(alias); } catch (err) { - // we bail to avoid retrying the whole process + // We bail to avoid retrying the whole process // of aliasing which would involve too many // retries on certificate provisioning return bail(err); } - // try again, but now having provisioned the certificate + // Try again, but now having provisioned the certificate return this.createAlias(depl, alias); } @@ -379,7 +380,7 @@ module.exports = class Alias extends Now { return bail(new Error(body.error.message)); } - // the two expected succesful cods are 200 and 304 + // The two expected succesful cods are 200 and 304 if (res.status !== 200 && res.status !== 304) { throw new Error('Unhandled error'); } @@ -429,13 +430,13 @@ module.exports = class Alias extends Now { } async maybeSetUpDomain(alias) { - // make alias lowercase + // Make alias lowercase alias = alias.toLowerCase(); - // trim leading and trailing dots + // Trim leading and trailing dots // for example: `google.com.` => `google.com` alias = alias.replace(/^\.+/, '').replace(/\.+$/, ''); - // evaluate the alias + // Evaluate the alias if (/\./.test(alias)) { alias = toHost(alias); } else { @@ -511,7 +512,7 @@ module.exports = class Alias extends Now { } } catch (err) { if (err.userError) { - // a user error would imply that verification failed + // A user error would imply that verification failed // in which case we attempt to correct the dns // configuration (if we can!) try { @@ -521,7 +522,7 @@ module.exports = class Alias extends Now { ); const record = alias.substr(0, alias.length - domain.length); - // lean up trailing and leading dots + // Lean up trailing and leading dots const _record = record.replace(/^\./, '').replace(/\.$/, ''); const _domain = domain.replace(/^\./, '').replace(/\.$/, ''); @@ -615,7 +616,7 @@ module.exports = class Alias extends Now { err.code === 'ESERVFAIL' || err.code === 'ENOTFOUND' ) { - // not errors per se, just absence of records + // Not errors per se, just absence of records if (this._debug) { console.log(`> [debug] No records found for "${domain}"`); } diff --git a/lib/build-logger.js b/lib/build-logger.js index 4e83305..879f6ff 100644 --- a/lib/build-logger.js +++ b/lib/build-logger.js @@ -39,7 +39,7 @@ module.exports = class Logger extends EventEmitter { this.debug = debug; this.quiet = quiet; - // readyState + // ReadyState this.building = false; this.socket = io(`https://io.now.sh/states?host=${host}&v=2`); @@ -50,12 +50,12 @@ module.exports = class Logger extends EventEmitter { this.lines = new Lines(10); - // log buffer + // Log buffer this.buf = []; } onState(state) { - // console.log(state) + // Console.log(state) if (!state.id) { console.error('> Deployment not found'); this.emit('error'); @@ -116,7 +116,7 @@ module.exports = class Logger extends EventEmitter { this.buf.sort((a, b) => compare(a.log, b.log)); - // flush all buffer + // Flush all buffer for (const b of this.buf) { clearTimeout(b.timer); this.printLog(b.log); diff --git a/lib/credit-cards.js b/lib/credit-cards.js index bcd02c0..1f4b281 100644 --- a/lib/credit-cards.js +++ b/lib/credit-cards.js @@ -57,14 +57,12 @@ module.exports = class CreditCards extends Now { last4: body.card.last4 }); } else if (body.error && body.error.message) { - reject({ message: body.error.message }); + reject(new Error(body.error.message)); } else { - reject('Unknown error'); + reject(new Error('Unknown error')); } } catch (err) { - reject({ - message: err.message || 'Unknown error' - }); + reject(new Error(err.message || 'Unknown error')); } }); } diff --git a/lib/domain-records.js b/lib/domain-records.js index cab34d9..f14bf23 100644 --- a/lib/domain-records.js +++ b/lib/domain-records.js @@ -29,28 +29,37 @@ module.exports = class DomainRecords extends Now { } const records = new Map(); + const bodies = []; + for (const domain of domains) { - const body = await this.retry(async (bail, attempt) => { - const url = `/domains/${domain}/records`; - if (this._debug) { - console.time(`> [debug] #${attempt} GET ${url}`); - } - const res = await this._fetch(url); - if (this._debug) { - console.timeEnd(`> [debug] #${attempt} GET ${url}`); - } - const body = await res.json(); + bodies.push( + this.retry(async (bail, attempt) => { + const url = `/domains/${domain}/records`; + if (this._debug) { + console.time(`> [debug] #${attempt} GET ${url}`); + } + const res = await this._fetch(url); + if (this._debug) { + console.timeEnd(`> [debug] #${attempt} GET ${url}`); + } + const body = await res.json(); + + if (res.status === 404 && body.code === 'not_found') { + return bail(new Error(body.message)); + } else if (res.status !== 200) { + throw new Error(`Failed to get DNS records for domain "${domain}"`); + } + + return body; + }) + ); + } - if (res.status === 404 && body.code === 'not_found') { - return bail(new Error(body.message)); - } else if (res.status !== 200) { - throw new Error(`Failed to get DNS records for domain "${domain}"`); - } + const domainList = await Promise.all(bodies); - return body; - }); + for (const body of domainList) { records.set( - domain, + body, body.records.sort((a, b) => a.slug.localeCompare(b.slug)) ); } diff --git a/lib/domains.js b/lib/domains.js index 38f10bb..3ba05bf 100644 --- a/lib/domains.js +++ b/lib/domains.js @@ -10,7 +10,8 @@ const domainRegex = /^((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a- module.exports = class Domains extends Now { async ls() { - return await this.listDomains(); + const domains = await this.listDomains(); + return domains; } async rm(name) { diff --git a/lib/get-files.js b/lib/get-files.js index 278600e..5c0d310 100644 --- a/lib/get-files.js +++ b/lib/get-files.js @@ -11,6 +11,57 @@ const { stat, readdir, readFile } = require('fs-promise'); // Ours const IGNORED = require('./ignored'); +const glob = async function(pattern, options) { + return new Promise((resolve, reject) => { + _glob(pattern, options, (error, files) => { + if (error) { + reject(error); + } else { + resolve(files); + } + }); + }); +}; + +/** + * Remove leading `./` from the beginning of ignores + * because our parser doesn't like them :| + */ + +const clearRelative = function(str) { + return str.replace(/(\n|^)\.\//g, '$1'); +}; + +/** + * Returns the contents of a file if it exists. + * + * @return {String} results or `''` + */ + +const maybeRead = async function(path, default_ = '') { + try { + return await readFile(path, 'utf8'); + } catch (err) { + return default_; + } +}; + +/** + * Transform relative paths into absolutes, + * and maintains absolutes as such. + * + * @param {String} maybe relative path + * @param {String} parent full path + */ + +const asAbsolute = function(path, parent) { + if (path[0] === '/') { + return path; + } + + return resolve(parent, path); +}; + /** * Returns a list of files in the given * directory that are subject to be @@ -36,10 +87,10 @@ async function npm( ) { const whitelist = (nowConfig && nowConfig.files) || pkg.files; - // the package.json `files` whitelist still + // The package.json `files` whitelist still // honors ignores: https://docs.npmjs.com/files/package.json#files const search_ = whitelist || ['.']; - // convert all filenames into absolute paths + // Convert all filenames into absolute paths const search = Array.prototype.concat.apply( [], await Promise.all( @@ -47,12 +98,12 @@ async function npm( ) ); - // always include the "main" file + // Always include the "main" file if (pkg.main) { - search.push(require.resolve(resolve(path, pkg.main), 'may-exclude')); // pkg: may-exclude suppresses warnings + search.push(require.resolve(resolve(path, pkg.main), 'may-exclude')); // Pkg: may-exclude suppresses warnings } - // compile list of ignored patterns and files + // Compile list of ignored patterns and files const npmIgnore = await maybeRead(resolve(path, '.npmignore'), null); const gitIgnore = npmIgnore === null ? await maybeRead(resolve(path, '.gitignore')) @@ -66,7 +117,7 @@ async function npm( const prefixLength = path.length + 1; - // the package.json `files` whitelist still + // The package.json `files` whitelist still // honors npmignores: https://docs.npmjs.com/files/package.json#files // but we don't ignore if the user is explicitly listing files // under the now namespace, or using files in combination with gitignore @@ -88,7 +139,7 @@ async function npm( return accepted; }; - // locate files + // Locate files if (debug) { console.time(`> [debug] locating files ${path}`); } @@ -103,7 +154,7 @@ async function npm( console.timeEnd(`> [debug] locating files ${path}`); } - // always include manifest as npm does not allow ignoring it + // Always include manifest as npm does not allow ignoring it // source: https://docs.npmjs.com/files/package.json#files files.push(asAbsolute('package.json', path)); @@ -111,26 +162,10 @@ async function npm( files.push(asAbsolute('now.json', path)); } - // get files + // Get files return unique(files); } -/** - * Transform relative paths into absolutes, - * and maintains absolutes as such. - * - * @param {String} maybe relative path - * @param {String} parent full path - */ - -const asAbsolute = function(path, parent) { - if (path[0] === '/') { - return path; - } - - return resolve(parent, path); -}; - /** * Returns a list of files in the given * directory that are subject to be @@ -155,15 +190,15 @@ async function docker( ) { const whitelist = nowConfig && nowConfig.files; - // base search path + // Base search path // the now.json `files` whitelist still // honors ignores: https://docs.npmjs.com/files/package.json#files const search_ = whitelist || ['.']; - // convert all filenames into absolute paths + // Convert all filenames into absolute paths const search = search_.map(file => asAbsolute(file, path)); - // compile list of ignored patterns and files + // Compile list of ignored patterns and files const dockerIgnore = await maybeRead(resolve(path, '.dockerignore'), null); const filter = ignore() @@ -193,7 +228,7 @@ async function docker( return accepted; }; - // locate files + // Locate files if (debug) { console.time(`> [debug] locating files ${path}`); } @@ -204,7 +239,7 @@ async function docker( console.timeEnd(`> [debug] locating files ${path}`); } - // always include manifest as npm does not allow ignoring it + // Always include manifest as npm does not allow ignoring it // source: https://docs.npmjs.com/files/package.json#files files.push(asAbsolute('Dockerfile', path)); @@ -212,22 +247,10 @@ async function docker( files.push(asAbsolute('now.json', path)); } - // get files + // Get files return unique(files); } -const glob = async function(pattern, options) { - return new Promise((resolve, reject) => { - _glob(pattern, options, (error, files) => { - if (error) { - reject(error); - } else { - resolve(files); - } - }); - }); -}; - /** * Explodes directories into a full list of files. * Eg: @@ -254,7 +277,7 @@ async function explode(paths, { accepts, debug }) { try { s = await stat(path); } catch (e) { - // in case the file comes from `files` or `main` + // In case the file comes from `files` or `main` // and it wasn't specified with `.js` by the user path = file + '.js'; @@ -270,7 +293,9 @@ async function explode(paths, { accepts, debug }) { if (s.isDirectory()) { const all = await readdir(file); + /* eslint-disable no-use-before-define */ return many(all.map(subdir => asAbsolute(subdir, file))); + /* eslint-enable no-use-before-define */ } else if (!s.isFile()) { if (debug) { console.log('> [debug] ignoring special file "%s"', file); @@ -282,39 +307,19 @@ async function explode(paths, { accepts, debug }) { }; const many = async all => { - return await Promise.all( + const awaitAll = await Promise.all( all.map(async file => { - return await list(file); + const listed = await list(file); + return listed; }) ); + + return awaitAll; }; return flatten(await many(paths)).filter(v => v !== null); } -/** - * Returns the contents of a file if it exists. - * - * @return {String} results or `''` - */ - -const maybeRead = async function(path, default_ = '') { - try { - return await readFile(path, 'utf8'); - } catch (err) { - return default_; - } -}; - -/** - * Remove leading `./` from the beginning of ignores - * because our parser doesn't like them :| - */ - -const clearRelative = function(str) { - return str.replace(/(\n|^)\.\//g, '$1'); -}; - module.exports = { npm, docker diff --git a/lib/git.js b/lib/git.js index 6a01710..e7d3198 100644 --- a/lib/git.js +++ b/lib/git.js @@ -50,55 +50,6 @@ const renameRepoDir = async (pathParts, tmpDir) => { return tmpDir; }; -const downloadRepo = async repoPath => { - const pathParts = gitPathParts(repoPath); - - const tmpDir = await tmp.dir({ - // We'll remove it manually once deployment is done - keep: true, - // Recursively remove directory when calling respective method - unsafeCleanup: true - }); - - let gitInstalled = true; - - try { - await cloneRepo(pathParts, tmpDir); - } catch (err) { - gitInstalled = false; - } - - if (gitInstalled) { - return await renameRepoDir(pathParts, tmpDir); - } - - let url; - - switch (pathParts.type) { - case 'GitLab': { - const ref = pathParts.ref ? `?ref=${pathParts.ref}` : ''; - url = `https://gitlab.com/${pathParts.main}/repository/archive.tar` + ref; - break; - } - case 'Bitbucket': - url = `https://bitbucket.org/${pathParts.main}/get/${pathParts.ref || 'default'}.zip`; - break; - default: - url = `https://api.github.com/repos/${pathParts.main}/tarball/${pathParts.ref}`; - } - - try { - await download(url, tmpDir.path, { - extract: true - }); - } catch (err) { - tmpDir.cleanup(); - return false; - } - - return await renameRepoDir(pathParts, tmpDir); -}; - const capitalizePlatform = name => { const names = { github: 'GitHub', @@ -166,6 +117,57 @@ const gitPathParts = main => { }; }; +const downloadRepo = async repoPath => { + const pathParts = gitPathParts(repoPath); + + const tmpDir = await tmp.dir({ + // We'll remove it manually once deployment is done + keep: true, + // Recursively remove directory when calling respective method + unsafeCleanup: true + }); + + let gitInstalled = true; + + try { + await cloneRepo(pathParts, tmpDir); + } catch (err) { + gitInstalled = false; + } + + if (gitInstalled) { + const renaming = await renameRepoDir(pathParts, tmpDir); + return renaming; + } + + let url; + + switch (pathParts.type) { + case 'GitLab': { + const ref = pathParts.ref ? `?ref=${pathParts.ref}` : ''; + url = `https://gitlab.com/${pathParts.main}/repository/archive.tar` + ref; + break; + } + case 'Bitbucket': + url = `https://bitbucket.org/${pathParts.main}/get/${pathParts.ref || 'default'}.zip`; + break; + default: + url = `https://api.github.com/repos/${pathParts.main}/tarball/${pathParts.ref}`; + } + + try { + await download(url, tmpDir.path, { + extract: true + }); + } catch (err) { + tmpDir.cleanup(); + return false; + } + + const renaming = await renameRepoDir(pathParts, tmpDir); + return renaming; +}; + const isRepoPath = path => { if (!path) { return false; diff --git a/lib/ignored.js b/lib/ignored.js index 253a807..6502e18 100644 --- a/lib/ignored.js +++ b/lib/ignored.js @@ -1,4 +1,4 @@ -// base `.gitignore` to which we add entries +// Base `.gitignore` to which we add entries // supplied by the user module.exports = `.hg .git diff --git a/lib/index.js b/lib/index.js index 4a0d5f7..bb54e7a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -19,11 +19,11 @@ const hash = require('./hash'); const Agent = require('./agent'); const readMetaData = require('./read-metadata'); -// how many concurrent HTTP/2 stream uploads +// How many concurrent HTTP/2 stream uploads const MAX_CONCURRENT = 10; -// check if running windows -const IS_WIN = /^win/.test(process.platform); +// Check if running windows +const IS_WIN = process.platform.startsWith('win'); const SEP = IS_WIN ? '\\' : '/'; module.exports = class Now extends EventEmitter { @@ -138,7 +138,7 @@ module.exports = class Now extends EventEmitter { Array.from(this._files).map(async ([sha, { data, names }]) => { const statFn = followSymlinks ? stat : lstat; - return await names.map(async name => { + const nameList = await names.map(async name => { let mode; const getMode = async () => { @@ -164,6 +164,8 @@ module.exports = class Now extends EventEmitter { mode }; }); + + return nameList; }) ) ) @@ -189,7 +191,7 @@ module.exports = class Now extends EventEmitter { console.timeEnd('> [debug] /now/create'); } - // no retry on 4xx + // No retry on 4xx let body; try { body = await res.json(); @@ -215,7 +217,7 @@ module.exports = class Now extends EventEmitter { return body; }); - // we report about files whose sizes are too big + // We report about files whose sizes are too big let missingVersion = false; if (deployment.warnings) { let sizeExceeded = 0; @@ -224,16 +226,16 @@ module.exports = class Now extends EventEmitter { const { sha, limit } = warning; const n = hashes.get(sha).names.pop(); console.error( - '> \u001b[31mWarning!\u001b[39m Skipping file %s (size exceeded %s)', + '> \u001B[31mWarning!\u001B[39m Skipping file %s (size exceeded %s)', n, bytes(limit) ); - hashes.get(sha).names.unshift(n); // move name (hack, if duplicate matches we report them in order) + hashes.get(sha).names.unshift(n); // Move name (hack, if duplicate matches we report them in order) sizeExceeded++; } else if (warning.reason === 'node_version_not_found') { const { wanted, used } = warning; console.error( - '> \u001b[31mWarning!\u001b[39m Requested node version %s is not available', + '> \u001B[31mWarning!\u001B[39m Requested node version %s is not available', wanted, used ); @@ -243,7 +245,7 @@ module.exports = class Now extends EventEmitter { if (sizeExceeded) { console.error( - `> \u001b[31mWarning!\u001b[39m ${sizeExceeded} of the files ` + + `> \u001B[31mWarning!\u001B[39m ${sizeExceeded} of the files ` + 'exceeded the limit for your plan.\n' + `> Please run ${chalk.gray('`')}${chalk.cyan('now upgrade')}${chalk.gray('`')} to upgrade.` ); @@ -334,7 +336,7 @@ module.exports = class Now extends EventEmitter { ); } - // no retry on 4xx + // No retry on 4xx if ( res.status !== 200 && (res.status >= 400 || res.status < 500) ) { @@ -392,7 +394,7 @@ module.exports = class Now extends EventEmitter { console.timeEnd('> [debug] /list'); } - // no retry on 4xx + // No retry on 4xx if (res.status >= 400 && res.status < 500) { if (this._debug) { console.log('> [debug] bailing on listing due to %s', res.status); @@ -471,7 +473,8 @@ module.exports = class Now extends EventEmitter { console.timeEnd(`> [debug] #${attempt} GET /domains/${domain}`); } - return await res.json(); + const parsedJSON = await res.json(); + return parsedJSON; }); } @@ -502,7 +505,7 @@ module.exports = class Now extends EventEmitter { if ( (!body.nameservers || body.nameservers.length === 0) && !fallback ) { - // if the nameservers are `null` it's likely + // If the nameservers are `null` it's likely // that our whois service failed to parse it fallback = true; throw new Error('Invalid whois response'); @@ -519,7 +522,7 @@ module.exports = class Now extends EventEmitter { }) .then(body => { body.nameservers = body.nameservers.filter(ns => { - // temporary hack: + // Temporary hack: // sometimes we get a response that looks like: // ['ns', 'ns', '', ''] // so we filter the empty ones @@ -566,7 +569,7 @@ module.exports = class Now extends EventEmitter { err.userError = true; return bail(err); } else if (res.status === 409) { - // domain already exists + // Domain already exists if (this._debug) { console.log('> [debug] Domain already exists (noop)'); } @@ -623,12 +626,12 @@ module.exports = class Now extends EventEmitter { 'This likely has to do with DNS propagation and caching issues. Please retry later!' ); err.userError = true; - // retry + // Retry throw err; } else if (code === 'rate_limited') { const err = new Error(body.error.message); err.userError = true; - // dont retry + // Dont retry return bail(err); } @@ -684,7 +687,7 @@ module.exports = class Now extends EventEmitter { console.timeEnd('> [debug] /remove'); } - // no retry on 4xx + // No retry on 4xx if (res.status >= 400 && res.status < 500) { if (this._debug) { console.log('> [debug] bailing on removal due to %s', res.status); diff --git a/lib/login.js b/lib/login.js index dc3c7bb..6e5d5fc 100644 --- a/lib/login.js +++ b/lib/login.js @@ -102,6 +102,7 @@ async function register(url, { retryEmail = false } = {}) { let final; + /* eslint-disable no-await-in-loop */ do { await sleep(2500); @@ -109,6 +110,7 @@ async function register(url, { retryEmail = false } = {}) { final = await verify(url, email, token); } catch (err) {} } while (!final); + /* eslint-enable no-await-in-loop */ spinner.text = 'Confirmed email address!'; spinner.stopAndPersist('✔'); diff --git a/lib/logs.js b/lib/logs.js index b58dbc1..27aaeec 100644 --- a/lib/logs.js +++ b/lib/logs.js @@ -1,6 +1,6 @@ exports.compare = function(a, b) { return a.serial.localeCompare(b.serial) || - // for the case serials are a same value on old logs + // For the case serials are a same value on old logs a.created.getTime() - b.created.getTime(); }; diff --git a/lib/pkg.js b/lib/pkg.js index 97a9ec8..93e2c52 100644 --- a/lib/pkg.js +++ b/lib/pkg.js @@ -1,3 +1,5 @@ +/* eslint-disable import/no-unresolved */ + let pkg; try { pkg = require('../package.json'); diff --git a/lib/plans.js b/lib/plans.js index 9b4e706..c06b674 100644 --- a/lib/plans.js +++ b/lib/plans.js @@ -28,7 +28,8 @@ module.exports = class Plans extends Now { async getCurrent() { const res = await this._fetch('/www/user/plan'); - return await parsePlan(res); + const parsedPlan = await parsePlan(res); + return parsedPlan; } async set(plan) { @@ -38,8 +39,10 @@ module.exports = class Plans extends Now { }); if (res.ok) { - return await parsePlan(res); + const parsedPlan = await parsePlan(res); + return parsedPlan; } + const err = new Error(res.statusText); err.res = res; throw err; diff --git a/lib/re-alias.js b/lib/re-alias.js index fc5126a..15b03fe 100644 --- a/lib/re-alias.js +++ b/lib/re-alias.js @@ -36,7 +36,7 @@ exports.reAlias = async (token, host, help, exit, apiUrl, debug, alias) => { } const { nowConfig, name } = await readMetaData(path, { - deploymentType: 'npm', // hard coding settings… + deploymentType: 'npm', // Hard coding settings… quiet: true // `quiet` }); @@ -80,7 +80,11 @@ exports.reAlias = async (token, host, help, exit, apiUrl, debug, alias) => { return exit(0); } + const assignments = []; + for (const pointer of pointers) { - await exports.assignAlias(pointer, token, host, apiUrl, debug); + assignments.push(exports.assignAlias(pointer, token, host, apiUrl, debug)); } + + await Promise.all(assignments); }; diff --git a/lib/read-metadata.js b/lib/read-metadata.js index d84d118..47c2e80 100644 --- a/lib/read-metadata.js +++ b/lib/read-metadata.js @@ -35,7 +35,7 @@ async function readMetaData( nowConfig = JSON.parse(await readFile(resolvePath(path, 'now.json'))); hasNowJson = true; } catch (err) { - // if the file doesn't exist then that's fine; any other error bubbles up + // If the file doesn't exist then that's fine; any other error bubbles up if (err.code !== 'ENOENT') { const e = Error(`Failed to read JSON in "${path}/now.json"`); e.userError = true; @@ -44,7 +44,7 @@ async function readMetaData( } if (hasNowJson) { - // user can specify the type of deployment explicitly in the `now.json` file + // User can specify the type of deployment explicitly in the `now.json` file // when both a package.json and Dockerfile exist if (nowConfig.type) { deploymentType = nowConfig.type; @@ -131,7 +131,7 @@ async function readMetaData( continue; } - // unescape and convert into string + // Unescape and convert into string try { labels[key] = JSON.parse(args[key]); } catch (err) { @@ -174,7 +174,7 @@ async function readMetaData( } if (pkg.now) { - // if the project has both a `now.json` and `now` Object in the `package.json` + // If the project has both a `now.json` and `now` Object in the `package.json` // file, then fail hard and let the user know that they need to pick one or the // other if (hasNowJson) { diff --git a/lib/strlen.js b/lib/strlen.js index 16cabda..d5910ed 100644 --- a/lib/strlen.js +++ b/lib/strlen.js @@ -1,5 +1,5 @@ function strlen(str) { - return str.replace(/\x1b[^m]*m/g, '').length; + return str.replace(/\u001b[^m]*m/g, '').length; } module.exports = strlen; diff --git a/lib/to-host.js b/lib/to-host.js index ab3f399..6c9422a 100644 --- a/lib/to-host.js +++ b/lib/to-host.js @@ -12,7 +12,7 @@ function toHost(url) { return parse(url).host; } - // remove any path if present + // Remove any path if present // `a.b.c/` => `a.b.c` return url.replace(/(\/\/)?([^/]+)(.*)/, '$2'); } diff --git a/lib/utils/exit.js b/lib/utils/exit.js index 022fadb..37d9e26 100644 --- a/lib/utils/exit.js +++ b/lib/utils/exit.js @@ -1,5 +1,5 @@ module.exports = code => { - // we give stdout some time to flush out + // We give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 diff --git a/lib/utils/input/list.js b/lib/utils/input/list.js index ca1f187..a3bd7fb 100644 --- a/lib/utils/input/list.js +++ b/lib/utils/input/list.js @@ -39,8 +39,8 @@ module.exports = async function( } ], pageSize = 15, // Show 15 lines without scrolling (~4 credit cards) - separator = true, // puts a blank separator between each choice - abort = 'end' // wether the `abort` option will be at the `start` or the `end` + separator = true, // Puts a blank separator between each choice + abort = 'end' // Wether the `abort` option will be at the `start` or the `end` } ) { let biggestLength = 0; diff --git a/lib/utils/input/prompt-bool.js b/lib/utils/input/prompt-bool.js index b974814..7f5d5e1 100644 --- a/lib/utils/input/prompt-bool.js +++ b/lib/utils/input/prompt-bool.js @@ -4,7 +4,7 @@ module.exports = ( label, { defaultValue = false, - abortSequences = new Set(['\x03']), + abortSequences = new Set(['\u0003']), resolveChars = new Set(['\r']), yesChar = 'y', noChar = 'n', diff --git a/lib/utils/input/text.js b/lib/utils/input/text.js index fcec97b..4fb7a92 100644 --- a/lib/utils/input/text.js +++ b/lib/utils/input/text.js @@ -4,11 +4,11 @@ const chalk = require('chalk'); const stripAnsi = require('strip-ansi'); const ESCAPES = { - LEFT: '\x1b[D', - RIGHT: '\x1b[C', - CTRL_C: '\x03', - BACKSPACE: '\x08', - CTRL_H: '\x7f', + LEFT: '\u001B[D', + RIGHT: '\u001B[C', + CTRL_C: '\u0003', + BACKSPACE: '\u0008', + CTRL_H: '\u007F', CARRIAGE: '\r' }; @@ -16,21 +16,21 @@ module.exports = function( { label = '', initialValue = '', - // can be: + // Can be: // - `false`, which does nothing // - `cc`, for credit cards // - `date`, for dates in the mm / yyyy format mask = false, placeholder = '', - abortSequences = new Set(['\x03']), + abortSequences = new Set(['\u0003']), eraseSequences = new Set([ESCAPES.BACKSPACE, ESCAPES.CTRL_H]), resolveChars = new Set([ESCAPES.CARRIAGE]), stdin = process.stdin, stdout = process.stdout, - // char to print before resolving/rejecting the promise + // Char to print before resolving/rejecting the promise // if `false`, nothing will be printed trailing = ansiEscapes.eraseLines(1), - // gets called on each keypress; + // Gets called on each keypress; // `data` contains the current keypress; // `futureValue` contains the current value + the // keypress in the correct place @@ -43,7 +43,7 @@ module.exports = function( autoComplete = value => false, // eslint-disable-line no-unused-vars // tab // right arrow - autoCompleteChars = new Set(['\t', '\x1b[C']) + autoCompleteChars = new Set(['\t', '\u001B[C']) } = {} ) { return new Promise((resolve, reject) => { diff --git a/lib/utils/output/cmd.js b/lib/utils/output/cmd.js index 4bafae2..e9403ab 100644 --- a/lib/utils/output/cmd.js +++ b/lib/utils/output/cmd.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); -// the equivalent of , for embedding a cmd +// The equivalent of , for embedding a cmd // eg: Please run ${cmd(woot)} module.exports = cmd => diff --git a/lib/utils/output/code.js b/lib/utils/output/code.js index aaf8f83..3b9ed1c 100644 --- a/lib/utils/output/code.js +++ b/lib/utils/output/code.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); -// the equivalent of , for embedding anything +// The equivalent of , for embedding anything // you may want to take a look at ./cmd.js module.exports = cmd => diff --git a/lib/utils/output/error.js b/lib/utils/output/error.js index d4b8c09..ca0b1fd 100644 --- a/lib/utils/output/error.js +++ b/lib/utils/output/error.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); -// prints an error message +// Prints an error message module.exports = msg => { console.error(`${chalk.red('> Error!')} ${msg}`); }; diff --git a/lib/utils/output/info.js b/lib/utils/output/info.js index 5d8beef..6a83f2a 100644 --- a/lib/utils/output/info.js +++ b/lib/utils/output/info.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); -// prints an informational message +// Prints an informational message module.exports = msg => { console.log(`${chalk.gray('>')} ${msg}`); }; diff --git a/lib/utils/output/param.js b/lib/utils/output/param.js index ded1381..90b631d 100644 --- a/lib/utils/output/param.js +++ b/lib/utils/output/param.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); -// returns a user param in a nice formatting +// Returns a user param in a nice formatting // e.g.: google.com -> "google.com" (in bold) module.exports = param => diff --git a/lib/utils/output/stamp.js b/lib/utils/output/stamp.js index 0a716b1..af643fe 100644 --- a/lib/utils/output/stamp.js +++ b/lib/utils/output/stamp.js @@ -1,7 +1,7 @@ const ms = require('ms'); const chalk = require('chalk'); -// returns a time delta with the right color +// Returns a time delta with the right color // example: `[103ms]` module.exports = () => { diff --git a/lib/utils/output/success.js b/lib/utils/output/success.js index 362e386..f1a9ef4 100644 --- a/lib/utils/output/success.js +++ b/lib/utils/output/success.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); -// prints a success message +// Prints a success message module.exports = msg => { console.log(`${chalk.cyan('> Success!')} ${msg}`); }; diff --git a/lib/utils/output/uid.js b/lib/utils/output/uid.js index e0e9cd0..8dd4ee1 100644 --- a/lib/utils/output/uid.js +++ b/lib/utils/output/uid.js @@ -1,5 +1,5 @@ const chalk = require('chalk'); -// used for including uids in the output +// Used for including uids in the output // example: `(dom_ji13dj2fih4fi2hf)` module.exports = id => chalk.gray(`(${id})`); diff --git a/lib/utils/output/wait.js b/lib/utils/output/wait.js index 0da6616..36efa6e 100644 --- a/lib/utils/output/wait.js +++ b/lib/utils/output/wait.js @@ -2,7 +2,7 @@ const ora = require('ora'); const chalk = require('chalk'); const { eraseLine } = require('ansi-escapes'); -// prints a spinner followed by the given text +// Prints a spinner followed by the given text module.exports = msg => { const spinner = ora(chalk.gray(msg)); spinner.color = 'gray'; diff --git a/lib/utils/to-human-path.js b/lib/utils/to-human-path.js index f03b0be..5fd123d 100644 --- a/lib/utils/to-human-path.js +++ b/lib/utils/to-human-path.js @@ -2,7 +2,7 @@ const { resolve } = require('path'); const { homedir } = require('os'); -// cleaned-up `$HOME` (i.e.: no trailing slash) +// Cleaned-up `$HOME` (i.e.: no trailing slash) const HOME = resolve(homedir()); /** diff --git a/package.json b/package.json index fec6665..d0f5c12 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ ], "scripts": { "precommit": "lint-staged", - "lint": "eslint lib/* bin/*", + "lint": "xo", "test": "npm run build && npm run lint && ava", "prepublish": "npm run build", "build": "./build.sh", @@ -30,20 +30,14 @@ "test/*.js" ] }, - "eslintConfig": { - "parserOptions": { - "ecmaVersion": 8 - }, - "extends": "eslint:recommended", - "env": { - "node": true, - "es6": true - }, - "rules": { - "no-console": 0, - "no-empty": 0, - "no-control-regex": 0 - } + "xo": { + "space": true, + "ignores": [ + "test/_fixtures/**" + ], + "extends": [ + "prettier" + ] }, "lint-staged": { "*.js": [ @@ -99,9 +93,10 @@ "devDependencies": { "alpha-sort": "2.0.0", "ava": "0.18.2", - "eslint": "3.18.0", + "eslint-config-prettier": "1.5.0", "husky": "0.13.3-0", "lint-staged": "3.4.0", - "pkg": "3.0.0-beta.29" + "pkg": "3.0.0-beta.29", + "xo": "0.18.0" } } diff --git a/readme.md b/readme.md index 9fd76bb..67fc19f 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,7 @@ # now CLI [![Build Status](https://travis-ci.org/zeit/now-cli.svg?branch=master)](https://travis-ci.org/zeit/now-cli) +[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo) [![Slack Channel](https://zeit-slackin.now.sh/badge.svg)](https://zeit.chat) Realtime global deployments served over HTTP/2. You can find the FAQs [here](https://zeit.co/now#frequently-asked-questions). diff --git a/test/index.js b/test/index.js index ab580f5..237cbcd 100644 --- a/test/index.js +++ b/test/index.js @@ -17,7 +17,7 @@ const prefix = join(__dirname, '_fixtures') + '/'; const base = path => path.replace(prefix, ''); const fixture = name => resolve(`./test/_fixtures/${name}`); -// overload to force debugging +// Overload to force debugging const getNpmFiles = async dir => { const { pkg, nowConfig, hasNowJson } = await readMetadata(dir, { quiet: true, diff --git a/test/to-host.js b/test/to-host.js index dfeddf0..9488962 100644 --- a/test/to-host.js +++ b/test/to-host.js @@ -1,38 +1,38 @@ const test = require('ava'); const toHost = require('../build/lib/to-host'); -test('simple', async t => { +test('simple', t => { t.is(toHost('zeit.co'), 'zeit.co'); }); -test('leading //', async t => { +test('leading //', t => { t.is( toHost('//zeit-logos-rnemgaicnc.now.sh'), 'zeit-logos-rnemgaicnc.now.sh' ); }); -test('leading http://', async t => { +test('leading http://', t => { t.is( toHost('http://zeit-logos-rnemgaicnc.now.sh'), 'zeit-logos-rnemgaicnc.now.sh' ); }); -test('leading https://', async t => { +test('leading https://', t => { t.is( toHost('https://zeit-logos-rnemgaicnc.now.sh'), 'zeit-logos-rnemgaicnc.now.sh' ); }); -test('leading https:// and path', async t => { +test('leading https:// and path', t => { t.is( toHost('https://zeit-logos-rnemgaicnc.now.sh/path'), 'zeit-logos-rnemgaicnc.now.sh' ); }); -test('simple and path', async t => { +test('simple and path', t => { t.is(toHost('zeit.co/test'), 'zeit.co'); });