nodely-cli
Version:
Console client for Nodely Platform
146 lines (119 loc) • 3.93 kB
JavaScript
/**
* 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,
};