#!/usr/bin/env node import program from 'commander'; import Progress from 'progress'; import copy from '../lib/copy'; import * as cfg from '../lib/cfg'; import { resolve } from 'path'; import login from '../lib/login'; import checkUpdate from '../lib/check-update'; import bytes from 'bytes'; import chalk from 'chalk'; import Now from '../lib'; import ms from 'ms'; program .usage('[options]') .option('-d, --debug', 'Debug mode [off]', false) .option('-f, --force', 'Force a new deployment even if nothing has changed', false) .option('-L, --login', 'Configure login') .option('-C, --no-clipboard', 'Do not attempt to copy URL to clipboard') .parse(process.argv); let path = program.args[program.args.length - 1]; if (path) { if ('/' !== path[0]) { path = resolve(process.cwd(), path); } } else { path = process.cwd(); } const debug = !!program.debug; const clipboard = !program.noClipboard; const config = cfg.read(); const update = checkUpdate({ debug }); const exit = (code) => { update.then(() => process.exit(code)); // don't wait for updates more than a second // when the process really wants to exit setTimeout(() => process.exit(code), 1000); }; if (!config.token || program.login) { login() .then((token) => { if (program.login) { console.log('> Logged in successfully. Token saved in ~/.now.json'); exit(0); } else { sync(token).catch((err) => { error(`Unknown error: ${err.stack}`); exit(1); }); } }) .catch((e) => { error(`Authentication error – ${e.message}`); exit(1); }); } else { sync(config.token).catch((err) => { error(`Unknown error: ${err.stack}`); exit(1); }); } async function sync (token) { const start = Date.now(); console.log(`> Deploying "${path}"`); const now = new Now(token, { debug }); try { await now.create(path, { forceNew: program.force }); } catch (err) { handleError(err); return; } const { url } = now; const elapsed = ms(new Date() - start); if (clipboard) { try { await copy(url); console.log(`> ${chalk.cyan('Ready!')} ${chalk.bold(`https://${url}`)} (copied to clipboard) [${elapsed}]`); } catch (err) { console.log(`> ${chalk.cyan('Ready!')} ${chalk.bold(`https://${url}`)} [${elapsed}]`); } } else { console.log(`> ${url} [${elapsed}]`); } const start_u = new Date(); const complete = () => { const elapsed_u = ms(new Date() - start_u); console.log(`> Sync complete (${bytes(now.syncAmount)}) [${elapsed_u}] `); now.close(); exit(0); }; if (now.syncAmount) { const bar = new Progress('> Upload [:bar] :percent :etas', { width: 20, complete: '=', incomplete: '', total: now.syncAmount }); now.upload(); now.on('upload', ({ name, data }) => { const amount = Buffer.byteLength(data); if (debug) { console.log(`> [debug] Uploaded: ${name} (${bytes(Buffer.byteLength(data))})`); } bar.tick(amount); }); now.on('complete', complete); now.on('error', (err) => { error('Upload failed'); handleError(err); exit(1); }); } else { console.log('> Sync complete (cached)'); now.close(); exit(0); } } function handleError (err) { if (403 === err.status) { error('Authentication error. Run `now -L` or `now --login` to log-in again.'); } else if (err.userError) { error(err.message); } else if (500 === err.status) { error('Unexpected server error. Please retry.'); } else { error(`Unexpected error. Please try later. (${err.message})`); } exit(1); } function error (err) { console.error(`> \u001b[31mError!\u001b[39m ${err}`); }