UNPKG

nodely-cli

Version:

Console client for Nodely Platform

146 lines (119 loc) 3.93 kB
/** * Created by Ivan Solovyev <support@nodely.me> * Date: 05/29/2018 * * Copyright @ Nodely, 2018 */ const fetch = require('node-fetch'); const tmp = require('tmp'); const fs = require('fs'); const https = require('https'); const API_URL = `${process.env.NCHOST || 'https://nodely.me'}/cli-api`; const METHOD_GET = 'GET'; const METHOD_POST = 'POST'; const METHOD_PUT = 'PUT'; let key = ''; let secret = ''; const init = (conf) => { key = conf.get('NC_KEY') || ''; secret = conf.get('NC_SECRET') || ''; }; const doReq = (method, resource, params) => { const headers = { 'X-NC-ACCESS-KEY': key, 'X-NC-SECRET-KEY': secret, }; if (process.env.NCDEBUG) { Object.keys(headers).forEach((ikey) => { console.log(`[header] ${ikey} = ${headers[ikey]}`); }); console.log(`[${method}] ${API_URL + resource}`); } return fetch(API_URL + resource, { method, headers, credentials: 'include', mode: 'cors', body: params ? JSON.stringify(params) : null, }).then((res) => { if (res.status >= 200 && res.status < 400) { if (res.status === 204) { return {}; } const contentType = res.headers.get('content-type'); if (contentType && contentType.indexOf('application/json') !== -1) { return res.json(); } return res.text(); } let message = res.statusText; if (res.status === 401) { message = 'You are not authorized to process this request. You need to invoke "nodely login" to obtain credentials.'; } if (res.status === 503) { message = 'We were unable to authorize this request. You need to re-invoke "nodely login" to obtain credentials.'; } if (res.status === 403) { message = 'You are not authorized to checkout this web site. Incident has been reported.'; } const err = new Error(message); err.statusCode = res.status; err.response = res; throw err; }); }; const getRepo = domain => doReq(METHOD_GET, `/checkout/${domain}`); const status = () => doReq(METHOD_GET, '/status'); const check = domain => doReq(METHOD_GET, `/check/${domain}`); const publish = (domain, mode, data) => doReq(METHOD_POST, `/publish/${domain}/${mode}`, { data }); const link = (domain, data) => doReq(METHOD_PUT, `/link/${domain}`, data); /** * Downloads by given url to temp file * * @param url * @param spinner * @returns {Promise<string>} */ const download = (url, spinner) => { const tmpobj = tmp.fileSync({ postfix: '.zip' }); const ws = fs.createWriteStream(tmpobj.name); return new Promise((resolve, reject) => { const timeout = 10000; let timeoutId; let fn; const timeoutWrapper = req => (() => { req.abort(); reject(new Error('File transfer timeout!')); }); const request = https.get(url).on('response', (res) => { const len = parseInt(res.headers['content-length'], 10); let downloaded = 0; res.on('data', (chunk) => { ws.write(chunk); downloaded += chunk.length; spinner.message(`Downloading ${(100.0 * downloaded / len).toFixed(2)}% ${downloaded} bytes\r`); // reset timeout clearTimeout(timeoutId); timeoutId = setTimeout(fn, timeout); }).on('end', () => { // clear timeout clearTimeout(timeoutId); ws.end(); resolve(tmpobj.name); }).on('error', (err) => { // clear timeout clearTimeout(timeoutId); reject(err.message); }); }); // generate timeout handler fn = timeoutWrapper(request); // set initial timeout timeoutId = setTimeout(fn, timeout); }); }; const putFiles = (domain, files) => doReq(METHOD_POST, `/file/${domain}`, files); const deleteFiles = (domain, files) => doReq(METHOD_POST, `/file/remove/${domain}`, files); module.exports = { getRepo, status, init, download, check, putFiles, deleteFiles, publish, link, };