')
.html(html)
- .appendTo($entry)
+ .appendTo($entry);
- $entry.height(height + $readme.outerHeight())
+ $entry.height(height + $readme.outerHeight());
transitionComplete(function() {
- $entry.css('height', 'auto')
- })
- }
- })
+ $entry.css('height', 'auto');
+ });
+ },
+ });
}
- })
-})
+ });
+});
diff --git a/lib/GUI/js/main.js b/lib/GUI/js/main.js
index eb5217414..d47de0253 100644
--- a/lib/GUI/js/main.js
+++ b/lib/GUI/js/main.js
@@ -1,13 +1,13 @@
// twitter bootstrap stuff;
// not in static 'cause I want it to be bundled with the rest of javascripts
-require('./bootstrap-modal')
+require('./bootstrap-modal');
// our own files
-require('./search')
-require('./entry')
+require('./search');
+require('./entry');
-var $ = require('unopinionate').selector
+let $ = require('unopinionate').selector;
$(document).on('click', '.js-userLogoutBtn', function() {
- $('#userLogoutForm').submit()
- return false
-})
+ $('#userLogoutForm').submit();
+ return false;
+});
diff --git a/lib/GUI/js/search.js b/lib/GUI/js/search.js
index 3b955f12b..d71736c33 100644
--- a/lib/GUI/js/search.js
+++ b/lib/GUI/js/search.js
@@ -1,5 +1,5 @@
-var $ = require('unopinionate').selector
-var template = require('../entry.hbs')
+let $ = require('unopinionate').selector;
+let template = require('../entry.hbs');
$(function() {
;(function(window, document) {
@@ -22,7 +22,8 @@ $(function() {
$form.bind('submit keyup', function(e) {
var query, isValidQuery
- e.preventDefault()
+
+ e.preventDefault();
query = $input.val()
isValidQuery = (query !== '')
@@ -31,35 +32,35 @@ $(function() {
if (!isValidQuery) {
if (request && typeof request.abort === 'function') {
- request.abort()
+ request.abort();
}
$searchResults.html('')
- return
+ return;
}
if (request && typeof request.abort === 'function') {
- request.abort()
+ request.abort();
}
if (query !== lastQuery) {
lastQuery = query
$searchResults.html(
- "

")
+ '

');
}
request = $.getJSON('-/search/' + query, function( results ) {
if (results.length > 0) {
- var html = ''
+ let html = '';
$.each(results, function(i, entry) {
- html += template(entry)
- })
+ html += template(entry);
+ });
- $searchResults.html(html)
+ $searchResults.html(html);
} else {
$searchResults.html(
- "
No Results
")
+ '
No Results
');
}
}).fail(function () {
$searchResults.html(
@@ -68,10 +69,9 @@ $(function() {
})
$(document).on('click', '.icon-cancel', function(e) {
- e.preventDefault()
- $input.val('')
- $form.keyup()
- })
-
- })(window, window.document)
-})
+ e.preventDefault();
+ $input.val('');
+ $form.keyup();
+ });
+ })(window, window.document);
+});
diff --git a/lib/auth.js b/lib/auth.js
index 1addcba6e..0f1caf2ec 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -1,33 +1,37 @@
-var Crypto = require('crypto')
-var jju = require('jju')
-var Error = require('http-errors')
-var Logger = require('./logger')
-var load_plugins = require('./plugin-loader').load_plugins
+/* eslint prefer-spread: "off" */
-module.exports = Auth
+'use strict';
+
+const Crypto = require('crypto');
+const jju = require('jju');
+const Error = require('http-errors');
+const Logger = require('./logger');
+const load_plugins = require('./plugin-loader').load_plugins;
+
+module.exports = Auth;
function Auth(config) {
- var self = Object.create(Auth.prototype)
- self.config = config
- self.logger = Logger.logger.child({ sub: 'auth' })
- self.secret = config.secret
+ let self = Object.create(Auth.prototype);
+ self.config = config;
+ self.logger = Logger.logger.child({sub: 'auth'});
+ self.secret = config.secret;
- var plugin_params = {
+ let plugin_params = {
config: config,
- logger: self.logger
- }
+ logger: self.logger,
+ };
if (config.users_file) {
if (!config.auth || !config.auth.htpasswd) {
// b/w compat
- config.auth = config.auth || {}
- config.auth.htpasswd = { file: config.users_file }
+ config.auth = config.auth || {};
+ config.auth.htpasswd = {file: config.users_file};
}
}
- self.plugins = load_plugins(config, config.auth, plugin_params, function (p) {
- return p.authenticate || p.allow_access || p.allow_publish
- })
+ self.plugins = load_plugins(config, config.auth, plugin_params, function(p) {
+ return p.authenticate || p.allow_access || p.allow_publish;
+ });
self.plugins.unshift({
verdaccio_version: '1.1.0',
@@ -38,342 +42,342 @@ function Auth(config) {
&& (Crypto.createHash('sha1').update(password).digest('hex')
=== config.users[user].password)
) {
- return cb(null, [ user ])
+ return cb(null, [user]);
}
- return cb()
+ return cb();
},
adduser: function(user, password, cb) {
if (config.users && config.users[user])
- return cb( Error[403]('this user already exists') )
+ return cb( Error[403]('this user already exists') );
- return cb()
+ return cb();
},
- })
+ });
function allow_action(action) {
- return function(user, package, cb) {
- var ok = package[action].reduce(function(prev, curr) {
- if (user.groups.indexOf(curr) !== -1) return true
- return prev
- }, false)
+ return function(user, pkg, cb) {
+ let ok = pkg[action].reduce(function(prev, curr) {
+ if (user.groups.indexOf(curr) !== -1) return true;
+ return prev;
+ }, false);
- if (ok) return cb(null, true)
+ if (ok) return cb(null, true);
if (user.name) {
- cb( Error[403]('user ' + user.name + ' is not allowed to ' + action + ' package ' + package.name) )
+ cb( Error[403]('user ' + user.name + ' is not allowed to ' + action + ' package ' + pkg.name) );
} else {
- cb( Error[403]('unregistered users are not allowed to ' + action + ' package ' + package.name) )
+ cb( Error[403]('unregistered users are not allowed to ' + action + ' package ' + pkg.name) );
}
- }
+ };
}
self.plugins.push({
authenticate: function(user, password, cb) {
- return cb( Error[403]('bad username/password, access denied') )
+ return cb( Error[403]('bad username/password, access denied') );
},
add_user: function(user, password, cb) {
- return cb( Error[409]('registration is disabled') )
+ return cb( Error[409]('registration is disabled') );
},
allow_access: allow_action('access'),
allow_publish: allow_action('publish'),
- })
+ });
- return self
+ return self;
}
Auth.prototype.authenticate = function(user, password, cb) {
- var plugins = this.plugins.slice(0)
+ let plugins = this.plugins.slice(0)
;(function next() {
- var p = plugins.shift()
+ let p = plugins.shift();
if (typeof(p.authenticate) !== 'function') {
- return next()
+ return next();
}
p.authenticate(user, password, function(err, groups) {
- if (err) return cb(err)
+ if (err) return cb(err);
if (groups != null && groups != false)
- return cb(err, AuthenticatedUser(user, groups))
- next()
- })
- })()
-}
+ return cb(err, authenticatedUser(user, groups));
+ next();
+ });
+ })();
+};
Auth.prototype.add_user = function(user, password, cb) {
- var self = this
- var plugins = this.plugins.slice(0)
+ let self = this;
+ let plugins = this.plugins.slice(0)
;(function next() {
- var p = plugins.shift()
- var n = 'adduser'
+ let p = plugins.shift();
+ let n = 'adduser';
if (typeof(p[n]) !== 'function') {
- n = 'add_user'
+ n = 'add_user';
}
if (typeof(p[n]) !== 'function') {
- next()
+ next();
} else {
p[n](user, password, function(err, ok) {
- if (err) return cb(err)
- if (ok) return self.authenticate(user, password, cb)
- next()
- })
+ if (err) return cb(err);
+ if (ok) return self.authenticate(user, password, cb);
+ next();
+ });
}
- })()
-}
+ })();
+};
Auth.prototype.allow_access = function(package_name, user, callback) {
- var plugins = this.plugins.slice(0)
- var package = Object.assign({ name: package_name },
+ let plugins = this.plugins.slice(0);
+ let pkg = Object.assign({name: package_name},
this.config.get_package_spec(package_name))
;(function next() {
- var p = plugins.shift()
+ let p = plugins.shift();
if (typeof(p.allow_access) !== 'function') {
- return next()
+ return next();
}
- p.allow_access(user, package, function(err, ok) {
- if (err) return callback(err)
- if (ok) return callback(null, ok)
- next() // cb(null, false) causes next plugin to roll
- })
- })()
-}
+ p.allow_access(user, pkg, function(err, ok) {
+ if (err) return callback(err);
+ if (ok) return callback(null, ok);
+ next(); // cb(null, false) causes next plugin to roll
+ });
+ })();
+};
Auth.prototype.allow_publish = function(package_name, user, callback) {
- var plugins = this.plugins.slice(0)
- var package = Object.assign({ name: package_name },
+ let plugins = this.plugins.slice(0);
+ let pkg = Object.assign({name: package_name},
this.config.get_package_spec(package_name))
;(function next() {
- var p = plugins.shift()
+ let p = plugins.shift();
if (typeof(p.allow_publish) !== 'function') {
- return next()
+ return next();
}
- p.allow_publish(user, package, function(err, ok) {
- if (err) return callback(err)
- if (ok) return callback(null, ok)
- next() // cb(null, false) causes next plugin to roll
- })
- })()
-}
+ p.allow_publish(user, pkg, function(err, ok) {
+ if (err) return callback(err);
+ if (ok) return callback(null, ok);
+ next(); // cb(null, false) causes next plugin to roll
+ });
+ })();
+};
Auth.prototype.basic_middleware = function() {
- var self = this
+ let self = this;
return function(req, res, _next) {
- req.pause()
+ req.pause();
function next(err) {
- req.resume()
+ req.resume();
// uncomment this to reject users with bad auth headers
- //return _next.apply(null, arguments)
+ // return _next.apply(null, arguments)
// swallow error, user remains unauthorized
// set remoteUserError to indicate that user was attempting authentication
- if (err) req.remote_user.error = err.message
- return _next()
+ if (err) req.remote_user.error = err.message;
+ return _next();
}
if (req.remote_user != null && req.remote_user.name !== undefined)
- return next()
- req.remote_user = AnonymousUser()
+ return next();
+ req.remote_user = buildAnonymousUser();
- var authorization = req.headers.authorization
- if (authorization == null) return next()
+ let authorization = req.headers.authorization;
+ if (authorization == null) return next();
- var parts = authorization.split(' ')
+ let parts = authorization.split(' ');
if (parts.length !== 2)
- return next( Error[400]('bad authorization header') )
+ return next( Error[400]('bad authorization header') );
- var scheme = parts[0]
+ let scheme = parts[0];
if (scheme === 'Basic') {
- var credentials = new Buffer(parts[1], 'base64').toString()
+ var credentials = new Buffer(parts[1], 'base64').toString();
} else if (scheme === 'Bearer') {
- var credentials = self.aes_decrypt(new Buffer(parts[1], 'base64')).toString('utf8')
- if (!credentials) return next()
+ var credentials = self.aes_decrypt(new Buffer(parts[1], 'base64')).toString('utf8');
+ if (!credentials) return next();
} else {
- return next()
+ return next();
}
- var index = credentials.indexOf(':')
- if (index < 0) return next()
+ let index = credentials.indexOf(':');
+ if (index < 0) return next();
- var user = credentials.slice(0, index)
- var pass = credentials.slice(index + 1)
+ let user = credentials.slice(0, index);
+ let pass = credentials.slice(index + 1);
self.authenticate(user, pass, function(err, user) {
if (!err) {
- req.remote_user = user
- next()
+ req.remote_user = user;
+ next();
} else {
- req.remote_user = AnonymousUser()
- next(err)
+ req.remote_user = buildAnonymousUser();
+ next(err);
}
- })
- }
-}
+ });
+ };
+};
Auth.prototype.bearer_middleware = function() {
- var self = this
+ let self = this;
return function(req, res, _next) {
- req.pause()
+ req.pause();
function next(_err) {
- req.resume()
- return _next.apply(null, arguments)
+ req.resume();
+ return _next.apply(null, arguments);
}
if (req.remote_user != null && req.remote_user.name !== undefined)
- return next()
- req.remote_user = AnonymousUser()
+ return next();
+ req.remote_user = buildAnonymousUser();
- var authorization = req.headers.authorization
- if (authorization == null) return next()
+ let authorization = req.headers.authorization;
+ if (authorization == null) return next();
- var parts = authorization.split(' ')
+ let parts = authorization.split(' ');
if (parts.length !== 2)
- return next( Error[400]('bad authorization header') )
+ return next( Error[400]('bad authorization header') );
- var scheme = parts[0]
- var token = parts[1]
+ let scheme = parts[0];
+ let token = parts[1];
if (scheme !== 'Bearer')
- return next()
+ return next();
try {
- var user = self.decode_token(token)
+ var user = self.decode_token(token);
} catch(err) {
- return next(err)
+ return next(err);
}
- req.remote_user = AuthenticatedUser(user.u, user.g)
- req.remote_user.token = token
- next()
- }
-}
+ req.remote_user = authenticatedUser(user.u, user.g);
+ req.remote_user.token = token;
+ next();
+ };
+};
Auth.prototype.cookie_middleware = function() {
- var self = this
+ let self = this;
return function(req, res, _next) {
- req.pause()
+ req.pause();
function next(_err) {
- req.resume()
- return _next()
+ req.resume();
+ return _next();
}
if (req.remote_user != null && req.remote_user.name !== undefined)
- return next()
+ return next();
- req.remote_user = AnonymousUser()
+ req.remote_user = buildAnonymousUser();
- var token = req.cookies.get('token')
- if (token == null) return next()
+ let token = req.cookies.get('token');
+ if (token == null) return next();
- /*try {
+ /* try {
var user = self.decode_token(token, 60*60)
} catch(err) {
return next()
}
- req.remote_user = AuthenticatedUser(user.u, user.g)
+ req.remote_user = authenticatedUser(user.u, user.g)
req.remote_user.token = token
next()*/
- var credentials = self.aes_decrypt(new Buffer(token, 'base64')).toString('utf8')
- if (!credentials) return next()
+ let credentials = self.aes_decrypt(new Buffer(token, 'base64')).toString('utf8');
+ if (!credentials) return next();
- var index = credentials.indexOf(':')
- if (index < 0) return next()
+ let index = credentials.indexOf(':');
+ if (index < 0) return next();
- var user = credentials.slice(0, index)
- var pass = credentials.slice(index + 1)
+ let user = credentials.slice(0, index);
+ let pass = credentials.slice(index + 1);
self.authenticate(user, pass, function(err, user) {
if (!err) {
- req.remote_user = user
- next()
+ req.remote_user = user;
+ next();
} else {
- req.remote_user = AnonymousUser()
- next(err)
+ req.remote_user = buildAnonymousUser();
+ next(err);
}
- })
- }
-}
+ });
+ };
+};
Auth.prototype.issue_token = function(user) {
- var data = jju.stringify({
+ let data = jju.stringify({
u: user.name,
g: user.real_groups && user.real_groups.length ? user.real_groups : undefined,
t: ~~(Date.now()/1000),
- }, { indent: false })
+ }, {indent: false});
- data = new Buffer(data, 'utf8')
- var mac = Crypto.createHmac('sha256', this.secret).update(data).digest()
- return Buffer.concat([ data, mac ]).toString('base64')
-}
+ data = new Buffer(data, 'utf8');
+ let mac = Crypto.createHmac('sha256', this.secret).update(data).digest();
+ return Buffer.concat([data, mac]).toString('base64');
+};
Auth.prototype.decode_token = function(str, expire_time) {
- var buf = new Buffer(str, 'base64')
- if (buf.length <= 32) throw Error[401]('invalid token')
+ let buf = new Buffer(str, 'base64');
+ if (buf.length <= 32) throw Error[401]('invalid token');
- var data = buf.slice(0, buf.length - 32)
- var their_mac = buf.slice(buf.length - 32)
- var good_mac = Crypto.createHmac('sha256', this.secret).update(data).digest()
+ let data = buf.slice(0, buf.length - 32);
+ let their_mac = buf.slice(buf.length - 32);
+ let good_mac = Crypto.createHmac('sha256', this.secret).update(data).digest();
- their_mac = Crypto.createHash('sha512').update(their_mac).digest('hex')
- good_mac = Crypto.createHash('sha512').update(good_mac).digest('hex')
- if (their_mac !== good_mac) throw Error[401]('bad signature')
+ their_mac = Crypto.createHash('sha512').update(their_mac).digest('hex');
+ good_mac = Crypto.createHash('sha512').update(good_mac).digest('hex');
+ if (their_mac !== good_mac) throw Error[401]('bad signature');
// make token expire in 24 hours
// TODO: make configurable?
- expire_time = expire_time || 24*60*60
+ expire_time = expire_time || 24*60*60;
- data = jju.parse(data.toString('utf8'))
+ data = jju.parse(data.toString('utf8'));
if (Math.abs(data.t - ~~(Date.now()/1000)) > expire_time)
- throw Error[401]('token expired')
+ throw Error[401]('token expired');
- return data
-}
+ return data;
+};
Auth.prototype.aes_encrypt = function(buf) {
- var c = Crypto.createCipher('aes192', this.secret)
- var b1 = c.update(buf)
- var b2 = c.final()
- return Buffer.concat([ b1, b2 ])
-}
+ let c = Crypto.createCipher('aes192', this.secret);
+ let b1 = c.update(buf);
+ let b2 = c.final();
+ return Buffer.concat([b1, b2]);
+};
Auth.prototype.aes_decrypt = function(buf) {
try {
- var c = Crypto.createDecipher('aes192', this.secret)
- var b1 = c.update(buf)
- var b2 = c.final()
+ let c = Crypto.createDecipher('aes192', this.secret);
+ let b1 = c.update(buf);
+ let b2 = c.final();
+ return Buffer.concat([b1, b2]);
} catch(_) {
- return new Buffer(0)
+ return new Buffer(0);
}
- return Buffer.concat([ b1, b2 ])
-}
+};
-function AnonymousUser() {
+function buildAnonymousUser() {
return {
name: undefined,
// groups without '$' are going to be deprecated eventually
- groups: [ '$all', '$anonymous', '@all', '@anonymous', 'all', 'undefined', 'anonymous' ],
+ groups: ['$all', '$anonymous', '@all', '@anonymous', 'all', 'undefined', 'anonymous'],
real_groups: [],
- }
+ };
}
-function AuthenticatedUser(name, groups) {
- var _groups = (groups || []).concat([ '$all', '$authenticated', '@all', '@authenticated', 'all' ])
+function authenticatedUser(name, groups) {
+ let _groups = (groups || []).concat(['$all', '$authenticated', '@all', '@authenticated', 'all']);
return {
name: name,
groups: _groups,
real_groups: groups,
- }
+ };
}
diff --git a/lib/cli.js b/lib/cli.js
index 6b079c69b..bea78c61e 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -1,114 +1,113 @@
#!/usr/bin/env node
-/*eslint no-sync:0*/
+/* eslint no-sync:0*/
+'use strict';
if (process.getuid && process.getuid() === 0) {
- global.console.error("Verdaccio doesn't need superuser privileges. Don't run it under root.")
+ global.console.error('Verdaccio doesn\'t need superuser privileges. Don\'t run it under root.');
}
-process.title = 'verdaccio'
-require('es6-shim')
+process.title = 'verdaccio';
try {
// for debugging memory leaks
// totally optional
- require('heapdump')
+ require('heapdump');
} catch(err) {}
-var logger = require('./logger')
-logger.setup() // default setup
+let logger = require('./logger');
+logger.setup(); // default setup
-var commander = require('commander')
-var constants = require('constants')
-var fs = require('fs')
-var http = require('http')
-var https = require('https')
-var YAML = require('js-yaml')
-var Path = require('path')
-var URL = require('url')
-var server = require('./index')
-var Utils = require('./utils')
-var pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
-var pkgVersion = module.exports.version
-var pkgName = module.exports.name
+let commander = require('commander');
+let constants = require('constants');
+let fs = require('fs');
+let http = require('http');
+let https = require('https');
+let YAML = require('js-yaml');
+let Path = require('path');
+let URL = require('url');
+let server = require('./index');
+let Utils = require('./utils');
+let pkginfo = require('pkginfo')(module); // eslint-disable-line no-unused-vars
+let pkgVersion = module.exports.version;
+let pkgName = module.exports.name;
commander
.option('-l, --listen <[host:]port>', 'host:port number to listen on (default: localhost:4873)')
.option('-c, --config
', 'use this configuration file (default: ./config.yaml)')
.version(pkgVersion)
- .parse(process.argv)
+ .parse(process.argv);
if (commander.args.length == 1 && !commander.config) {
// handling "verdaccio [config]" case if "-c" is missing in commandline
- commander.config = commander.args.pop()
+ commander.config = commander.args.pop();
}
if (commander.args.length != 0) {
- commander.help()
+ commander.help();
}
-var config, config_path
+let config, config_path;
try {
if (commander.config) {
- config_path = Path.resolve(commander.config)
+ config_path = Path.resolve(commander.config);
} else {
- config_path = require('./config-path')()
+ config_path = require('./config-path')();
}
- config = YAML.safeLoad(fs.readFileSync(config_path, 'utf8'))
- logger.logger.warn({ file: config_path }, 'config file - @{file}')
+ config = YAML.safeLoad(fs.readFileSync(config_path, 'utf8'));
+ logger.logger.warn({file: config_path}, 'config file - @{file}');
} catch (err) {
- logger.logger.fatal({ file: config_path, err: err }, 'cannot open config file @{file}: @{!err.message}')
- process.exit(1)
+ logger.logger.fatal({file: config_path, err: err}, 'cannot open config file @{file}: @{!err.message}');
+ process.exit(1);
}
-afterConfigLoad()
+afterConfigLoad();
function get_listen_addresses() {
// command line || config file || default
- var addresses
+ let addresses;
if (commander.listen) {
- addresses = [ commander.listen ]
+ addresses = [commander.listen];
} else if (Array.isArray(config.listen)) {
- addresses = config.listen
+ addresses = config.listen;
} else if (config.listen) {
- addresses = [ config.listen ]
+ addresses = [config.listen];
} else {
- addresses = [ '4873' ]
+ addresses = ['4873'];
}
addresses = addresses.map(function(addr) {
- var parsed_addr = Utils.parse_address(addr)
+ let parsed_addr = Utils.parse_address(addr);
if (!parsed_addr) {
- logger.logger.warn({ addr: addr },
+ logger.logger.warn({addr: addr},
'invalid address - @{addr}, we expect a port (e.g. "4873"),'
+ ' host:port (e.g. "localhost:4873") or full url'
- + ' (e.g. "http://localhost:4873/")')
+ + ' (e.g. "http://localhost:4873/")');
}
- return parsed_addr
+ return parsed_addr;
+ }).filter(Boolean);
- }).filter(Boolean)
-
- return addresses
+ return addresses;
}
function afterConfigLoad() {
- if (!config.self_path) config.self_path = Path.resolve(config_path)
- if (!config.https) config.https = { enable: false };
+ if (!config.self_path) config.self_path = Path.resolve(config_path);
+ if (!config.https) config.https = {enable: false};
- var app = server(config)
+ let app = server(config);
get_listen_addresses().forEach(function(addr) {
- var webServer
+ let webServer;
if (addr.proto === 'https') { // https
if (!config.https || !config.https.key || !config.https.cert) {
- var conf_path = function(file) {
- if (!file) return config_path
- return Path.resolve(Path.dirname(config_path), file)
- }
+ let conf_path = function(file) {
+ if (!file) return config_path;
+ return Path.resolve(Path.dirname(config_path), file);
+ };
logger.logger.fatal([
'You need to specify "https.key" and "https.cert" to run https server',
@@ -123,8 +122,8 @@ function afterConfigLoad() {
' https:',
' key: verdaccio-key.pem',
' cert: verdaccio-cert.pem',
- ].join('\n'))
- process.exit(2)
+ ].join('\n'));
+ process.exit(2);
}
try {
@@ -133,12 +132,11 @@ function afterConfigLoad() {
secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3,
key: fs.readFileSync(config.https.key),
cert: fs.readFileSync(config.https.cert),
- ca: fs.readFileSync(config.https.ca)
-
- }, app)
+ ca: fs.readFileSync(config.https.ca),
+ }, app);
} catch (err) { // catch errors related to certificate loading
- logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}')
- process.exit(2)
+ logger.logger.fatal({err: err}, 'cannot create server: @{err.message}');
+ process.exit(2);
}
} else { // http
webServer = http.createServer(app);
@@ -147,9 +145,9 @@ function afterConfigLoad() {
webServer
.listen(addr.port || addr.path, addr.host)
.on('error', function(err) {
- logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}')
- process.exit(2)
- })
+ logger.logger.fatal({err: err}, 'cannot create server: @{err.message}');
+ process.exit(2);
+ });
logger.logger.warn({
addr: ( addr.path
@@ -165,17 +163,17 @@ function afterConfigLoad() {
})
),
version: pkgName + '/' + pkgVersion,
- }, 'http address - @{addr}')
- })
+ }, 'http address - @{addr}');
+ });
// undocumented stuff for tests
if (typeof(process.send) === 'function') {
- process.send({ verdaccio_started: true })
+ process.send({verdaccio_started: true});
}
}
process.on('uncaughtException', function(err) {
- logger.logger.fatal( { err: err }
- , 'uncaught exception, please report this\n@{err.stack}' )
- process.exit(255)
-})
+ logger.logger.fatal( {err: err}
+ , 'uncaught exception, please report this\n@{err.stack}' );
+ process.exit(255);
+});
diff --git a/lib/config-path.js b/lib/config-path.js
index 6cb7a2236..b83aa0e72 100644
--- a/lib/config-path.js
+++ b/lib/config-path.js
@@ -1,47 +1,49 @@
-var fs = require('fs')
-var Path = require('path')
-var logger = require('./logger')
+'use strict';
-module.exports = find_config_file
+let fs = require('fs');
+let Path = require('path');
+let logger = require('./logger');
+
+module.exports = find_config_file;
function find_config_file() {
- var paths = get_paths()
+ let paths = get_paths();
- for (var i=0; i [a, b, c, d]
function flatten(array) {
- var result = []
- for (var i=0; i= last_suffix
- || (m[4] === '' && last_suffix !== Infinity)) {
- throw Error('invalid interval: ' + interval)
+ || parse_interval_table[m[4]] >= last_suffix
+ || (m[4] === '' && last_suffix !== Infinity)) {
+ throw Error('invalid interval: ' + interval);
}
- last_suffix = parse_interval_table[m[4]]
- result += Number(m[1]) * parse_interval_table[m[4]]
- })
- return result
-}
+ last_suffix = parse_interval_table[m[4]];
+ result += Number(m[1]) * parse_interval_table[m[4]];
+ });
+ return result;
+};
diff --git a/lib/file-locking.js b/lib/file-locking.js
index 7b19e2e25..e2c0e619e 100644
--- a/lib/file-locking.js
+++ b/lib/file-locking.js
@@ -1,15 +1,17 @@
+'use strict';
+
/**
* file-locking.js - file system locking (replaces fs-ext)
*/
-var async = require('async'),
+let async = require('async'),
locker = require('lockfile'),
fs = require('fs'),
- path = require('path')
+ path = require('path');
// locks a file by creating a lock file
function lockFile(name, next) {
- var lockFileName = name + '.lock',
+ let lockFileName = name + '.lock',
lockOpts = {
wait: 1000, // time (ms) to wait when checking for stale locks
pollPeriod: 100, // how often (ms) to re-check stale locks
@@ -17,65 +19,64 @@ function lockFile(name, next) {
stale: 5 * 60 * 1000, // locks are considered stale after 5 minutes
retries: 100, // number of times to attempt to create a lock
- retryWait: 100 // time (ms) between tries
- }
+ retryWait: 100, // time (ms) between tries
+ };
async.series({
- statdir: function (callback) {
+ statdir: function(callback) {
// test to see if the directory exists
- fs.stat(path.dirname(name), function (err, stats) {
+ fs.stat(path.dirname(name), function(err, stats) {
if (err) {
- callback(err)
+ callback(err);
} else if (!stats.isDirectory()) {
- callback(new Error(path.dirname(name) + ' is not a directory'))
+ callback(new Error(path.dirname(name) + ' is not a directory'));
} else {
- callback(null)
- }
- })
- },
-
- statfile: function (callback) {
- // test to see if the file to lock exists
- fs.stat(name, function (err, stats) {
- if (err) {
- callback(err)
- } else if (!stats.isFile()) {
- callback(new Error(path.dirname(name) + ' is not a file'))
- } else {
- callback(null)
+ callback(null);
}
});
},
- lockfile: function (callback) {
- // try to lock the file
- locker.lock(lockFileName, lockOpts, callback)
- }
+ statfile: function(callback) {
+ // test to see if the file to lock exists
+ fs.stat(name, function(err, stats) {
+ if (err) {
+ callback(err);
+ } else if (!stats.isFile()) {
+ callback(new Error(path.dirname(name) + ' is not a file'));
+ } else {
+ callback(null);
+ }
+ });
+ },
- }, function (err) {
+ lockfile: function(callback) {
+ // try to lock the file
+ locker.lock(lockFileName, lockOpts, callback);
+ },
+
+ }, function(err) {
if (err) {
// lock failed
- return next(err)
+ return next(err);
}
// lock succeeded
return next(null);
- })
-
+ });
}
// unlocks file by removing existing lock file
function unlockFile(name, next) {
- var lockFileName = name + '.lock'
+ let lockFileName = name + '.lock';
- locker.unlock(lockFileName, function (err) {
+ locker.unlock(lockFileName, function(err) {
if (err) {
- return next(err)
+ return next(err);
}
- return next(null)
- })
+ return next(null);
+ });
}
/**
@@ -87,63 +88,62 @@ function unlockFile(name, next) {
function readFile(name, options, next) {
if (typeof options === 'function' && next === null) {
next = options;
- options = {}
+ options = {};
}
- options = options || {}
- options.lock = options.lock || false
- options.parse = options.parse || false
+ options = options || {};
+ options.lock = options.lock || false;
+ options.parse = options.parse || false;
function lock(callback) {
if (!options.lock) {
- return callback(null)
+ return callback(null);
}
- lockFile(name, function (err) {
+ lockFile(name, function(err) {
if (err) {
- return callback(err)
+ return callback(err);
}
- return callback(null)
- })
+ return callback(null);
+ });
}
function read(callback) {
- fs.readFile(name, 'utf8', function (err, contents) {
+ fs.readFile(name, 'utf8', function(err, contents) {
if (err) {
- return callback(err)
+ return callback(err);
}
- callback(null, contents)
-
- })
+ callback(null, contents);
+ });
}
function parseJSON(contents, callback) {
if (!options.parse) {
- return callback(null, contents)
+ return callback(null, contents);
}
try {
- contents = JSON.parse(contents)
- return callback(null, contents)
+ contents = JSON.parse(contents);
+ return callback(null, contents);
} catch (err) {
- return callback(err)
+ return callback(err);
}
}
async.waterfall([
lock,
read,
- parseJSON
+ parseJSON,
],
- function (err, result) {
+ function(err, result) {
if (err) {
- return next(err)
+ return next(err);
} else {
- return next(null, result)
+ return next(null, result);
}
- })
+ });
}
exports.lockFile = lockFile;
diff --git a/lib/index-api.js b/lib/index-api.js
index c624de91d..f9cb68610 100644
--- a/lib/index-api.js
+++ b/lib/index-api.js
@@ -1,106 +1,108 @@
-var Cookies = require('cookies')
-var express = require('express')
-var bodyParser = require('body-parser')
-var Error = require('http-errors')
-var Path = require('path')
-var Middleware = require('./middleware')
-var Notify = require('./notify')
-var Utils = require('./utils')
-var expect_json = Middleware.expect_json
-var match = Middleware.match
-var media = Middleware.media
-var validate_name = Middleware.validate_name
-var validate_pkg = Middleware.validate_package
+'use strict';
+
+let Cookies = require('cookies');
+let express = require('express');
+let bodyParser = require('body-parser');
+let Error = require('http-errors');
+let Path = require('path');
+let Middleware = require('./middleware');
+let Notify = require('./notify');
+let Utils = require('./utils');
+let expect_json = Middleware.expect_json;
+let match = Middleware.match;
+let media = Middleware.media;
+let validate_name = Middleware.validate_name;
+let validate_pkg = Middleware.validate_package;
module.exports = function(config, auth, storage) {
- var app = express.Router()
- var can = Middleware.allow(auth)
- var notify = Notify.notify;
+ let app = express.Router();
+ let can = Middleware.allow(auth);
+ let notify = Notify.notify;
// validate all of these params as a package name
// this might be too harsh, so ask if it causes trouble
- app.param('package', validate_pkg)
- app.param('filename', validate_name)
- app.param('tag', validate_name)
- app.param('version', validate_name)
- app.param('revision', validate_name)
- app.param('token', validate_name)
+ app.param('package', validate_pkg);
+ app.param('filename', validate_name);
+ app.param('tag', validate_name);
+ app.param('version', validate_name);
+ app.param('revision', validate_name);
+ app.param('token', validate_name);
// these can't be safely put into express url for some reason
- app.param('_rev', match(/^-rev$/))
- app.param('org_couchdb_user', match(/^org\.couchdb\.user:/))
- app.param('anything', match(/.*/))
+ app.param('_rev', match(/^-rev$/));
+ app.param('org_couchdb_user', match(/^org\.couchdb\.user:/));
+ app.param('anything', match(/.*/));
- app.use(auth.basic_middleware())
- //app.use(auth.bearer_middleware())
- app.use(bodyParser.json({ strict: false, limit: config.max_body_size || '10mb' }))
- app.use(Middleware.anti_loop(config))
+ app.use(auth.basic_middleware());
+ // app.use(auth.bearer_middleware())
+ app.use(bodyParser.json({strict: false, limit: config.max_body_size || '10mb'}));
+ app.use(Middleware.anti_loop(config));
// encode / in a scoped package name to be matched as a single parameter in routes
app.use(function(req, res, next) {
if (req.url.indexOf('@') != -1) {
// e.g.: /@org/pkg/1.2.3 -> /@org%2Fpkg/1.2.3, /@org%2Fpkg/1.2.3 -> /@org%2Fpkg/1.2.3
- req.url = req.url.replace(/^(\/@[^\/%]+)\/(?!$)/, '$1%2F')
+ req.url = req.url.replace(/^(\/@[^\/%]+)\/(?!$)/, '$1%2F');
}
- next()
- })
+ next();
+ });
// for "npm whoami"
app.get('/whoami', function(req, res, next) {
if (req.headers.referer === 'whoami') {
- next({ username: req.remote_user.name })
+ next({username: req.remote_user.name});
} else {
- next('route')
+ next('route');
}
- })
+ });
app.get('/-/whoami', function(req, res, next) {
- next({ username: req.remote_user.name })
- })
+ next({username: req.remote_user.name});
+ });
// TODO: anonymous user?
app.get('/:package/:version?', can('access'), function(req, res, next) {
- storage.get_package(req.params.package, { req: req }, function(err, info) {
- if (err) return next(err)
- info = Utils.filter_tarball_urls(info, req, config)
+ storage.get_package(req.params.package, {req: req}, function(err, info) {
+ if (err) return next(err);
+ info = Utils.filter_tarball_urls(info, req, config);
- var version = req.params.version
- if (!version) return next(info)
+ let version = req.params.version;
+ if (!version) return next(info);
- var t = Utils.get_version(info, version)
- if (t != null) return next(t)
+ let t = Utils.get_version(info, version);
+ if (t != null) return next(t);
if (info['dist-tags'] != null) {
if (info['dist-tags'][version] != null) {
- version = info['dist-tags'][version]
- t = Utils.get_version(info, version)
- if (t != null) return next(t)
+ version = info['dist-tags'][version];
+ t = Utils.get_version(info, version);
+ if (t != null) return next(t);
}
}
- return next( Error[404]('version not found: ' + req.params.version) )
- })
- })
+ return next( Error[404]('version not found: ' + req.params.version) );
+ });
+ });
app.get('/:package/-/:filename', can('access'), function(req, res, next) {
- var stream = storage.get_tarball(req.params.package, req.params.filename)
+ let stream = storage.get_tarball(req.params.package, req.params.filename);
stream.on('content-length', function(v) {
- res.header('Content-Length', v)
- })
+ res.header('Content-Length', v);
+ });
stream.on('error', function(err) {
- return res.report_error(err)
- })
- res.header('Content-Type', 'application/octet-stream')
- stream.pipe(res)
- })
+ return res.report_error(err);
+ });
+ res.header('Content-Type', 'application/octet-stream');
+ stream.pipe(res);
+ });
// searching packages
app.get('/-/all(\/since)?', function(req, res, next) {
- var received_end = false
- var response_finished = false
- var processing_pkgs = 0
- var firstPackage = true
+ let received_end = false;
+ let response_finished = false;
+ let processing_pkgs = 0;
+ let firstPackage = true;
- res.status(200)
+ res.status(200);
/*
* Offical NPM registry (registry.npmjs.org) no longer return whole database,
@@ -120,105 +122,105 @@ module.exports = function(config, auth, storage) {
* Data structure also different, whel request /-/all, response is an object, but
* when request /-/all/since, response is an array
*/
- var respShouldBeArray = req.path.endsWith('/since')
- res.set('Date', 'Mon, 10 Oct 1983 00:12:48 GMT')
+ const respShouldBeArray = req.path.endsWith('/since');
+ res.set('Date', 'Mon, 10 Oct 1983 00:12:48 GMT');
if (respShouldBeArray) {
- res.write('[')
+ res.write('[');
} else {
res.write('{"_updated":' + 99999);
}
- var stream = storage.search(req.query.startkey || 0, { req: req })
+ let stream = storage.search(req.query.startkey || 0, {req: req});
stream.on('data', function each(pkg) {
- processing_pkgs++
+ processing_pkgs++;
auth.allow_access(pkg.name, req.remote_user, function(err, allowed) {
- processing_pkgs--
+ processing_pkgs--;
if (err) {
if (err.status && String(err.status).match(/^4\d\d$/)) {
// auth plugin returns 4xx user error,
// that's equivalent of !allowed basically
- allowed = false
+ allowed = false;
} else {
- stream.abort(err)
+ stream.abort(err);
}
}
if (allowed) {
if (respShouldBeArray) {
- res.write(`${firstPackage ? '' : ','}${JSON.stringify(pkg)}\n`)
+ res.write(`${firstPackage ? '' : ','}${JSON.stringify(pkg)}\n`);
if (firstPackage) {
- firstPackage = false
+ firstPackage = false;
}
} else {
- res.write(',\n' + JSON.stringify(pkg.name) + ':' + JSON.stringify(pkg))
+ res.write(',\n' + JSON.stringify(pkg.name) + ':' + JSON.stringify(pkg));
}
}
- check_finish()
- })
- })
+ check_finish();
+ });
+ });
- stream.on('error', function (_err) {
- res.socket.destroy()
- })
+ stream.on('error', function(_err) {
+ res.socket.destroy();
+ });
- stream.on('end', function () {
- received_end = true
- check_finish()
- })
+ stream.on('end', function() {
+ received_end = true;
+ check_finish();
+ });
function check_finish() {
- if (!received_end) return
- if (processing_pkgs) return
- if (response_finished) return
+ if (!received_end) return;
+ if (processing_pkgs) return;
+ if (response_finished) return;
- response_finished = true
+ response_finished = true;
if (respShouldBeArray) {
- res.end(']\n')
+ res.end(']\n');
} else {
- res.end('}\n')
+ res.end('}\n');
}
}
- })
+ });
// placeholder 'cause npm require to be authenticated to publish
// we do not do any real authentication yet
app.post('/_session', Cookies.express(), function(req, res, next) {
res.cookies.set('AuthSession', String(Math.random()), {
// npmjs.org sets 10h expire
- expires: new Date(Date.now() + 10*60*60*1000)
- })
- next({ ok: true, name: 'somebody', roles: [] })
- })
+ expires: new Date(Date.now() + 10*60*60*1000),
+ });
+ next({ok: true, name: 'somebody', roles: []});
+ });
app.get('/-/user/:org_couchdb_user', function(req, res, next) {
- res.status(200)
+ res.status(200);
next({
ok: 'you are authenticated as "' + req.remote_user.name + '"',
- })
- })
+ });
+ });
app.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function(req, res, next) {
- var token = (req.body.name && req.body.password)
+ let token = (req.body.name && req.body.password)
? auth.aes_encrypt(req.body.name + ':' + req.body.password).toString('base64')
- : undefined
+ : undefined;
if (req.remote_user.name != null) {
- res.status(201)
+ res.status(201);
return next({
- ok: "you are authenticated as '" + req.remote_user.name + "'",
- //token: auth.issue_token(req.remote_user),
+ ok: 'you are authenticated as \'' + req.remote_user.name + '\'',
+ // token: auth.issue_token(req.remote_user),
token: token,
- })
+ });
} else {
if (typeof(req.body.name) !== 'string' || typeof(req.body.password) !== 'string') {
if (typeof(req.body.password_sha)) {
- return next( Error[422]('your npm version is outdated\nPlease update to npm@1.4.5 or greater.\nSee https://github.com/rlidwka/sinopia/issues/93 for details.') )
+ return next( Error[422]('your npm version is outdated\nPlease update to npm@1.4.5 or greater.\nSee https://github.com/rlidwka/sinopia/issues/93 for details.') );
} else {
- return next( Error[422]('user/password is not found in request (npm issue?)') )
+ return next( Error[422]('user/password is not found in request (npm issue?)') );
}
}
auth.add_user(req.body.name, req.body.password, function(err, user) {
@@ -227,133 +229,130 @@ module.exports = function(config, auth, storage) {
// With npm registering is the same as logging in,
// and npm accepts only an 409 error.
// So, changing status code here.
- return next( Error[409](err.message) )
+ return next( Error[409](err.message) );
}
- return next(err)
+ return next(err);
}
- req.remote_user = user
- res.status(201)
+ req.remote_user = user;
+ res.status(201);
return next({
- ok: "user '" + req.body.name + "' created",
- //token: auth.issue_token(req.remote_user),
+ ok: 'user \'' + req.body.name + '\' created',
+ // token: auth.issue_token(req.remote_user),
token: token,
- })
- })
+ });
+ });
}
- })
+ });
app.delete('/-/user/token/*', function(req, res, next) {
- res.status(200)
+ res.status(200);
next({
ok: 'Logged out',
- })
- })
+ });
+ });
function tag_package_version(req, res, next) {
- if (typeof(req.body) !== 'string') return next('route')
+ if (typeof(req.body) !== 'string') return next('route');
- var tags = {}
- tags[req.params.tag] = req.body
+ let tags = {};
+ tags[req.params.tag] = req.body;
storage.merge_tags(req.params.package, tags, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'package tagged' })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'package tagged'});
+ });
}
// tagging a package
app.put('/:package/:tag',
- can('publish'), media('application/json'), tag_package_version)
+ can('publish'), media('application/json'), tag_package_version);
app.post('/-/package/:package/dist-tags/:tag',
- can('publish'), media('application/json'), tag_package_version)
+ can('publish'), media('application/json'), tag_package_version);
app.put('/-/package/:package/dist-tags/:tag',
- can('publish'), media('application/json'), tag_package_version)
+ can('publish'), media('application/json'), tag_package_version);
- app.delete('/-/package/:package/dist-tags/:tag', can('publish'), function (req, res, next) {
- var tags = {}
- tags[req.params.tag] = null
+ app.delete('/-/package/:package/dist-tags/:tag', can('publish'), function(req, res, next) {
+ let tags = {};
+ tags[req.params.tag] = null;
storage.merge_tags(req.params.package, tags, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'tag removed' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'tag removed'});
+ });
+ });
app.get('/-/package/:package/dist-tags', can('access'), function(req, res, next) {
- storage.get_package(req.params.package, { req: req }, function(err, info) {
- if (err) return next(err)
+ storage.get_package(req.params.package, {req: req}, function(err, info) {
+ if (err) return next(err);
- next(info['dist-tags'])
- })
- })
+ next(info['dist-tags']);
+ });
+ });
app.post('/-/package/:package/dist-tags',
can('publish'), media('application/json'), expect_json,
function(req, res, next) {
-
storage.merge_tags(req.params.package, req.body, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'tags updated' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'tags updated'});
+ });
+ });
app.put('/-/package/:package/dist-tags',
can('publish'), media('application/json'), expect_json,
function(req, res, next) {
-
storage.replace_tags(req.params.package, req.body, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'tags updated' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'tags updated'});
+ });
+ });
app.delete('/-/package/:package/dist-tags',
can('publish'), media('application/json'),
function(req, res, next) {
-
storage.replace_tags(req.params.package, {}, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'tags removed' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'tags removed'});
+ });
+ });
// publishing a package
app.put('/:package/:_rev?/:revision?', can('publish'), media('application/json'), expect_json, function(req, res, next) {
- var name = req.params.package
+ let name = req.params.package;
if (Object.keys(req.body).length == 1 && Utils.is_object(req.body.users)) {
// 501 status is more meaningful, but npm doesn't show error message for 5xx
- return next( Error[404]('npm star|unstar calls are not implemented') )
+ return next( Error[404]('npm star|unstar calls are not implemented') );
}
try {
- var metadata = Utils.validate_metadata(req.body, name)
+ var metadata = Utils.validate_metadata(req.body, name);
} catch(err) {
- return next( Error[422]('bad incoming package data') )
+ return next( Error[422]('bad incoming package data') );
}
if (req.params._rev) {
storage.change_package(name, metadata, req.params.revision, function(err) {
- after_change(err, 'package changed')
- })
+ after_change(err, 'package changed');
+ });
} else {
storage.add_package(name, metadata, function(err) {
- after_change(err, 'created new package')
- })
+ after_change(err, 'created new package');
+ });
}
function after_change(err, ok_message) {
// old npm behaviour
if (metadata._attachments == null) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: ok_message })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: ok_message});
}
// npm-registry-client 0.3+ embeds tarball into the json upload
@@ -361,121 +360,120 @@ module.exports = function(config, auth, storage) {
// issue #31, dealing with it here:
if (typeof(metadata._attachments) !== 'object'
- || Object.keys(metadata._attachments).length !== 1
- || typeof(metadata.versions) !== 'object'
- || Object.keys(metadata.versions).length !== 1) {
-
+ || Object.keys(metadata._attachments).length !== 1
+ || typeof(metadata.versions) !== 'object'
+ || Object.keys(metadata.versions).length !== 1) {
// npm is doing something strange again
// if this happens in normal circumstances, report it as a bug
- return next( Error[400]('unsupported registry call') )
+ return next( Error[400]('unsupported registry call') );
}
- if (err && err.status != 409) return next(err)
+ if (err && err.status != 409) return next(err);
// at this point document is either created or existed before
- var t1 = Object.keys(metadata._attachments)[0]
+ let t1 = Object.keys(metadata._attachments)[0];
create_tarball(Path.basename(t1), metadata._attachments[t1], function(err) {
- if (err) return next(err)
+ if (err) return next(err);
- var t2 = Object.keys(metadata.versions)[0]
- metadata.versions[t2].readme = metadata.readme != null ? String(metadata.readme) : ''
+ let t2 = Object.keys(metadata.versions)[0];
+ metadata.versions[t2].readme = metadata.readme != null ? String(metadata.readme) : '';
create_version(t2, metadata.versions[t2], function(err) {
- if (err) return next(err)
+ if (err) return next(err);
add_tags(metadata['dist-tags'], function(err) {
- if (err) return next(err)
- notify(metadata, config)
- res.status(201)
- return next({ ok: ok_message })
- })
- })
- })
+ if (err) return next(err);
+ notify(metadata, config);
+ res.status(201);
+ return next({ok: ok_message});
+ });
+ });
+ });
}
function create_tarball(filename, data, cb) {
- var stream = storage.add_tarball(name, filename)
+ let stream = storage.add_tarball(name, filename);
stream.on('error', function(err) {
- cb(err)
- })
+ cb(err);
+ });
stream.on('success', function() {
- cb()
- })
+ cb();
+ });
// this is dumb and memory-consuming, but what choices do we have?
- stream.end(new Buffer(data.data, 'base64'))
- stream.done()
+ stream.end(new Buffer(data.data, 'base64'));
+ stream.done();
}
function create_version(version, data, cb) {
- storage.add_version(name, version, data, null, cb)
+ storage.add_version(name, version, data, null, cb);
}
function add_tags(tags, cb) {
- storage.merge_tags(name, tags, cb)
+ storage.merge_tags(name, tags, cb);
}
- })
+ });
// unpublishing an entire package
app.delete('/:package/-rev/*', can('publish'), function(req, res, next) {
storage.remove_package(req.params.package, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'package removed' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'package removed'});
+ });
+ });
// removing a tarball
app.delete('/:package/-/:filename/-rev/:revision', can('publish'), function(req, res, next) {
storage.remove_tarball(req.params.package, req.params.filename, req.params.revision, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'tarball removed' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'tarball removed'});
+ });
+ });
// uploading package tarball
app.put('/:package/-/:filename/*', can('publish'), media('application/octet-stream'), function(req, res, next) {
- var name = req.params.package
+ let name = req.params.package;
- var stream = storage.add_tarball(name, req.params.filename)
- req.pipe(stream)
+ let stream = storage.add_tarball(name, req.params.filename);
+ req.pipe(stream);
// checking if end event came before closing
- var complete = false
+ let complete = false;
req.on('end', function() {
- complete = true
- stream.done()
- })
+ complete = true;
+ stream.done();
+ });
req.on('close', function() {
if (!complete) {
- stream.abort()
+ stream.abort();
}
- })
+ });
stream.on('error', function(err) {
- return res.report_error(err)
- })
+ return res.report_error(err);
+ });
stream.on('success', function() {
- res.status(201)
+ res.status(201);
return next({
- ok: 'tarball uploaded successfully'
- })
- })
- })
+ ok: 'tarball uploaded successfully',
+ });
+ });
+ });
// adding a version
app.put('/:package/:version/-tag/:tag', can('publish'), media('application/json'), expect_json, function(req, res, next) {
- var name = req.params.package
- var version = req.params.version
- var tag = req.params.tag
+ let name = req.params.package;
+ let version = req.params.version;
+ let tag = req.params.tag;
storage.add_version(name, version, req.body, tag, function(err) {
- if (err) return next(err)
- res.status(201)
- return next({ ok: 'package published' })
- })
- })
+ if (err) return next(err);
+ res.status(201);
+ return next({ok: 'package published'});
+ });
+ });
- return app
-}
+ return app;
+};
diff --git a/lib/index-web.js b/lib/index-web.js
index 22b9a36dc..3c2c92644 100644
--- a/lib/index-web.js
+++ b/lib/index-web.js
@@ -1,167 +1,167 @@
-var async = require('async')
-var bodyParser = require('body-parser')
-var Cookies = require('cookies')
-var express = require('express')
-var fs = require('fs')
-var Handlebars = require('handlebars')
-var renderReadme = require('render-readme')
-var Search = require('./search')
-var Middleware = require('./middleware')
-var match = Middleware.match
-var validate_name = Middleware.validate_name
-var validate_pkg = Middleware.validate_package
+'use strict';
+
+let async = require('async');
+let bodyParser = require('body-parser');
+let Cookies = require('cookies');
+let express = require('express');
+let fs = require('fs');
+let Handlebars = require('handlebars');
+let renderReadme = require('render-readme');
+let Search = require('./search');
+let Middleware = require('./middleware');
+let match = Middleware.match;
+let validate_name = Middleware.validate_name;
+let validate_pkg = Middleware.validate_package;
module.exports = function(config, auth, storage) {
- var app = express.Router()
- var can = Middleware.allow(auth)
+ let app = express.Router();
+ let can = Middleware.allow(auth);
// validate all of these params as a package name
// this might be too harsh, so ask if it causes trouble
- app.param('package', validate_pkg)
- app.param('filename', validate_name)
- app.param('version', validate_name)
- app.param('anything', match(/.*/))
+ app.param('package', validate_pkg);
+ app.param('filename', validate_name);
+ app.param('version', validate_name);
+ app.param('anything', match(/.*/));
- app.use(Cookies.express())
- app.use(bodyParser.urlencoded({ extended: false }))
- app.use(auth.cookie_middleware())
+ app.use(Cookies.express());
+ app.use(bodyParser.urlencoded({extended: false}));
+ app.use(auth.cookie_middleware());
app.use(function(req, res, next) {
// disable loading in frames (clickjacking, etc.)
- res.header('X-Frame-Options', 'deny')
- next()
- })
+ res.header('X-Frame-Options', 'deny');
+ next();
+ });
- Search.configureStorage(storage)
+ Search.configureStorage(storage);
- Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.hbs'), 'utf8'))
-
- if(config.web && config.web.template) {
- var template = Handlebars.compile(fs.readFileSync(config.web.template, 'utf8'));
- }
- else {
- var template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.hbs'), 'utf8'))
+ Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.hbs'), 'utf8'));
+ let template;
+ if (config.web && config.web.template) {
+ template = Handlebars.compile(fs.readFileSync(config.web.template, 'utf8'));
+ } else {
+ template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.hbs'), 'utf8'));
}
app.get('/', function(req, res, next) {
- var base = config.url_prefix
+ let base = config.url_prefix
? config.url_prefix.replace(/\/$/, '')
- : req.protocol + '://' + req.get('host')
- res.setHeader('Content-Type', 'text/html')
+ : req.protocol + '://' + req.get('host');
+ res.setHeader('Content-Type', 'text/html');
storage.get_local(function(err, packages) {
- if (err) throw err // that function shouldn't produce any
- async.filterSeries(packages, function(package, cb) {
- auth.allow_access(package.name, req.remote_user, function(err, allowed) {
- setImmediate(function () {
+ if (err) throw err; // that function shouldn't produce any
+ async.filterSeries(packages, function(pkg, cb) {
+ auth.allow_access(pkg.name, req.remote_user, function(err, allowed) {
+ setImmediate(function() {
if (err) {
cb(null, false);
} else {
- cb(err, allowed)
+ cb(err, allowed);
}
- })
- })
+ });
+ });
}, function(err, packages) {
- if (err) throw err
+ if (err) throw err;
packages.sort(function(p1, p2) {
if (p1.name < p2.name) {
return -1;
- }
- else {
+ } else {
return 1;
}
});
next(template({
- name: config.web && config.web.title ? config.web.title : 'Verdaccio',
- tagline: config.web && config.web.tagline ? config.web.tagline : '',
- packages: packages,
- baseUrl: base,
- username: req.remote_user.name,
- }))
- })
- })
- })
+ name: config.web && config.web.title ? config.web.title : 'Verdaccio',
+ tagline: config.web && config.web.tagline ? config.web.tagline : '',
+ packages: packages,
+ baseUrl: base,
+ username: req.remote_user.name,
+ }));
+ });
+ });
+ });
// Static
app.get('/-/static/:filename', function(req, res, next) {
- var file = __dirname + '/static/' + req.params.filename
+ let file = __dirname + '/static/' + req.params.filename;
res.sendFile(file, function(err) {
- if (!err) return
+ if (!err) return;
if (err.status === 404) {
- next()
+ next();
} else {
- next(err)
+ next(err);
}
- })
- })
+ });
+ });
app.get('/-/logo', function(req, res, next) {
res.sendFile( config.web && config.web.logo
? config.web.logo
- : __dirname + '/static/logo-sm.png' )
- })
+ : __dirname + '/static/logo-sm.png' );
+ });
app.post('/-/login', function(req, res, next) {
auth.authenticate(req.body.user, req.body.pass, function(err, user) {
if (!err) {
- req.remote_user = user
- //res.cookies.set('token', auth.issue_token(req.remote_user))
+ req.remote_user = user;
+ // res.cookies.set('token', auth.issue_token(req.remote_user))
- var str = req.body.user + ':' + req.body.pass
- res.cookies.set('token', auth.aes_encrypt(str).toString('base64'))
+ let str = req.body.user + ':' + req.body.pass;
+ res.cookies.set('token', auth.aes_encrypt(str).toString('base64'));
}
- var base = config.url_prefix
+ let base = config.url_prefix
? config.url_prefix.replace(/\/$/, '')
- : req.protocol + '://' + req.get('host')
- res.redirect(base)
- })
- })
+ : req.protocol + '://' + req.get('host');
+ res.redirect(base);
+ });
+ });
app.post('/-/logout', function(req, res, next) {
- var base = config.url_prefix
+ let base = config.url_prefix
? config.url_prefix.replace(/\/$/, '')
- : req.protocol + '://' + req.get('host')
- res.cookies.set('token', '')
- res.redirect(base)
- })
+ : req.protocol + '://' + req.get('host');
+ res.cookies.set('token', '');
+ res.redirect(base);
+ });
// Search
app.get('/-/search/:anything', function(req, res, next) {
- var results = Search.query(req.params.anything)
- var packages = []
+ const results = Search.query(req.params.anything);
+ const packages = [];
- var getData = function(i) {
+ const getData = function(i) {
storage.get_package(results[i].ref, function(err, entry) {
if (!err && entry) {
auth.allow_access(entry.name, req.remote_user, function(err, allowed) { // TODO: This may cause performance issue?
- if (err || !allowed) return
+ if (err || !allowed) return;
- packages.push(entry.versions[entry['dist-tags'].latest])
- })
+ packages.push(entry.versions[entry['dist-tags'].latest]);
+ });
}
if (i >= results.length - 1) {
- next(packages)
+ next(packages);
} else {
- getData(i + 1)
+ getData(i + 1);
}
- })
- }
+ });
+ };
if (results.length) {
- getData(0)
+ getData(0);
} else {
- next([])
+ next([]);
}
- })
+ });
app.get('/-/readme(/@:scope?)?/:package/:version?', can('access'), function(req, res, next) {
- var packageName = req.params.package;
- if (req.params.scope) packageName = "@"+ req.params.scope + "/" + packageName;
+ let packageName = req.params.package;
+ if (req.params.scope) packageName = '@'+ req.params.scope + '/' + packageName;
storage.get_package(packageName, {req: req}, function(err, info) {
- if (err) return next(err)
- next( renderReadme(info.readme || 'ERROR: No README data found!') )
- })
- })
- return app
-}
+ if (err) return next(err);
+ next( renderReadme(info.readme || 'ERROR: No README data found!') );
+ });
+ });
+ return app;
+};
diff --git a/lib/index.js b/lib/index.js
index 8e9c8ecc8..f244a1653 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,105 +1,107 @@
-var express = require('express')
-var Error = require('http-errors')
-var compression = require('compression')
-var Auth = require('./auth')
-var Logger = require('./logger')
-var Config = require('./config')
-var Middleware = require('./middleware')
-var Cats = require('./status-cats')
-var Storage = require('./storage')
+'use strict';
+
+let express = require('express');
+let Error = require('http-errors');
+let compression = require('compression');
+let Auth = require('./auth');
+let Logger = require('./logger');
+let Config = require('./config');
+let Middleware = require('./middleware');
+let Cats = require('./status-cats');
+let Storage = require('./storage');
module.exports = function(config_hash) {
- Logger.setup(config_hash.logs)
+ Logger.setup(config_hash.logs);
- var config = Config(config_hash)
- var storage = Storage(config)
- var auth = Auth(config)
- var app = express()
+ let config = Config(config_hash);
+ let storage = new Storage(config);
+ let auth = Auth(config);
+ let app = express();
// run in production mode by default, just in case
// it shouldn't make any difference anyway
- app.set('env', process.env.NODE_ENV || 'production')
+ app.set('env', process.env.NODE_ENV || 'production');
function error_reporting_middleware(req, res, next) {
res.report_error = res.report_error || function(err) {
if (err.status && err.status >= 400 && err.status < 600) {
if (!res.headersSent) {
- res.status(err.status)
- next({ error: err.message || 'unknown error' })
+ res.status(err.status);
+ next({error: err.message || 'unknown error'});
}
} else {
- Logger.logger.error( { err: err }
- , 'unexpected error: @{!err.message}\n@{err.stack}')
+ Logger.logger.error( {err: err}
+ , 'unexpected error: @{!err.message}\n@{err.stack}');
if (!res.status || !res.send) {
- Logger.logger.error('this is an error in express.js, please report this')
- res.destroy()
+ Logger.logger.error('this is an error in express.js, please report this');
+ res.destroy();
} else if (!res.headersSent) {
- res.status(500)
- next({ error: 'internal server error' })
+ res.status(500);
+ next({error: 'internal server error'});
} else {
// socket should be already closed
}
}
- }
- next()
+ };
+ next();
}
- app.use(Middleware.log)
- app.use(error_reporting_middleware)
+ app.use(Middleware.log);
+ app.use(error_reporting_middleware);
app.use(function(req, res, next) {
- res.setHeader('X-Powered-By', config.user_agent)
- next()
- })
- app.use(Cats.middleware)
- app.use(compression())
+ res.setHeader('X-Powered-By', config.user_agent);
+ next();
+ });
+ app.use(Cats.middleware);
+ app.use(compression());
app.get('/favicon.ico', function(req, res, next) {
- req.url = '/-/static/favicon.png'
- next()
- })
+ req.url = '/-/static/favicon.png';
+ next();
+ });
// hook for tests only
if (config._debug) {
app.get('/-/_debug', function(req, res, next) {
- var do_gc = typeof(global.gc) !== 'undefined'
- if (do_gc) global.gc()
+ let do_gc = typeof(global.gc) !== 'undefined';
+ if (do_gc) global.gc();
next({
- pid : process.pid,
- main : process.mainModule.filename,
- conf : config.self_path,
- mem : process.memoryUsage(),
- gc : do_gc,
- })
- })
+ pid: process.pid,
+ main: process.mainModule.filename,
+ conf: config.self_path,
+ mem: process.memoryUsage(),
+ gc: do_gc,
+ });
+ });
}
- app.use(require('./index-api')(config, auth, storage))
+ app.use(require('./index-api')(config, auth, storage));
if (config.web && config.web.enable === false) {
app.get('/', function(req, res, next) {
- next( Error[404]('web interface is disabled in the config file') )
- })
+ next( Error[404]('web interface is disabled in the config file') );
+ });
} else {
- app.use(require('./index-web')(config, auth, storage))
+ app.use(require('./index-web')(config, auth, storage));
}
app.get('/*', function(req, res, next) {
- next( Error[404]('file not found') )
- })
+ next( Error[404]('file not found') );
+ });
app.use(function(err, req, res, next) {
- if (Object.prototype.toString.call(err) !== '[object Error]') return next(err)
- if (err.code === 'ECONNABORT' && res.statusCode === 304) return next()
+ if (Object.prototype.toString.call(err) !== '[object Error]') return next(err);
+ if (err.code === 'ECONNABORT' && res.statusCode === 304) return next();
if (typeof(res.report_error) !== 'function') {
// in case of very early error this middleware may not be loaded before error is generated
// fixing that
- error_reporting_middleware(req, res, function(){})
+ error_reporting_middleware(req, res, function() {});
}
- res.report_error(err)
- })
+ res.report_error(err);
+ });
- app.use(Middleware.final)
+ app.use(Middleware.final);
- return app
-}
+ return app;
+};
diff --git a/lib/local-data.js b/lib/local-data.js
index bc050562b..7da7999a9 100644
--- a/lib/local-data.js
+++ b/lib/local-data.js
@@ -1,44 +1,46 @@
-var fs = require('fs')
-var Path = require('path')
+'use strict';
-module.exports = LocalData
+const fs = require('fs');
+const Path = require('path');
-function LocalData(path) {
- var self = Object.create(LocalData.prototype)
- self.path = path
- try {
- self.data = JSON.parse(fs.readFileSync(self.path, 'utf8'))
- } catch(_) {
- self.data = { list: [] }
- }
- return self
-}
+ class LocalData {
-LocalData.prototype.add = function(name) {
- if (this.data.list.indexOf(name) === -1) {
- this.data.list.push(name)
- this.sync()
- }
-}
-
-LocalData.prototype.remove = function(name) {
- var i = this.data.list.indexOf(name)
- if (i !== -1) {
- this.data.list.splice(i, 1)
+ constructor(path) {
+ this.path = path;
+ try {
+ this.data = JSON.parse(fs.readFileSync(this.path, 'utf8'));
+ } catch(_) {
+ this.data = {list: []};
+ }
+ }
+
+ add(name) {
+ if (this.data.list.indexOf(name) === -1) {
+ this.data.list.push(name);
+ this.sync();
+ }
+ }
+
+ remove(name) {
+ const i = this.data.list.indexOf(name);
+ if (i !== -1) {
+ this.data.list.splice(i, 1);
+ }
+ this.sync();
+ }
+
+ get() {
+ return this.data.list;
+ }
+
+ sync() {
+ // Uses sync to prevent ugly race condition
+ try {
+ require('mkdirp').sync(Path.dirname(this.path));
+ } catch(err) {}
+ fs.writeFileSync(this.path, JSON.stringify(this.data));
}
- this.sync()
-}
-
-LocalData.prototype.get = function() {
- return this.data.list
-}
-
-LocalData.prototype.sync = function() {
- // Uses sync to prevent ugly race condition
- try {
- require('mkdirp').sync(Path.dirname(this.path))
- } catch(err) {}
- fs.writeFileSync(this.path, JSON.stringify(this.data))
}
+module.exports = LocalData;
diff --git a/lib/local-fs.js b/lib/local-fs.js
index f742a063c..fd8a64379 100644
--- a/lib/local-fs.js
+++ b/lib/local-fs.js
@@ -1,213 +1,215 @@
-var fs = require('fs')
-var Error = require('http-errors')
-var mkdirp = require('mkdirp')
-var Path = require('path')
-var MyStreams = require('./streams')
+'use strict';
+
+const fs = require('fs');
+const Error = require('http-errors');
+const mkdirp = require('mkdirp');
+const Path = require('path');
+const MyStreams = require('./streams');
function FSError(code) {
- var err = Error(code)
- err.code = code
- return err
+ let err = Error(code);
+ err.code = code;
+ return err;
}
-var locker = require('./file-locking')
+let locker = require('./file-locking');
function tempFile(str) {
- return str + '.tmp' + String(Math.random()).substr(2)
+ return str + '.tmp' + String(Math.random()).substr(2);
}
function renameTmp(src, dst, _cb) {
function cb(err) {
- if (err) fs.unlink(src, function() {})
- _cb(err)
+ if (err) fs.unlink(src, function() {});
+ _cb(err);
}
if (process.platform !== 'win32') {
- return fs.rename(src, dst, cb)
+ return fs.rename(src, dst, cb);
}
// windows can't remove opened file,
// but it seem to be able to rename it
- var tmp = tempFile(dst)
+ let tmp = tempFile(dst);
fs.rename(dst, tmp, function(err) {
- fs.rename(src, dst, cb)
- if (!err) fs.unlink(tmp, function () {})
- })
+ fs.rename(src, dst, cb);
+ if (!err) fs.unlink(tmp, () => {});
+ });
}
function write(dest, data, cb) {
- var safe_write = function(cb) {
- var tmpname = tempFile(dest)
+ let safe_write = function(cb) {
+ let tmpname = tempFile(dest);
fs.writeFile(tmpname, data, function(err) {
- if (err) return cb(err)
- renameTmp(tmpname, dest, cb)
- })
- }
+ if (err) return cb(err);
+ renameTmp(tmpname, dest, cb);
+ });
+ };
safe_write(function(err) {
if (err && err.code === 'ENOENT') {
mkdirp(Path.dirname(dest), function(err) {
- if (err) return cb(err)
- safe_write(cb)
- })
+ if (err) return cb(err);
+ safe_write(cb);
+ });
} else {
- cb(err)
+ cb(err);
}
- })
+ });
}
function write_stream(name) {
- var stream = MyStreams.UploadTarballStream()
+ let stream = MyStreams.UploadTarballStream();
- var _ended = 0
+ let _ended = 0;
stream.on('end', function() {
- _ended = 1
- })
+ _ended = 1;
+ });
fs.exists(name, function(exists) {
- if (exists) return stream.emit('error', FSError('EEXISTS'))
+ if (exists) return stream.emit('error', FSError('EEXISTS'));
- var tmpname = name + '.tmp-'+String(Math.random()).replace(/^0\./, '')
- var file = fs.createWriteStream(tmpname)
- var opened = false
- stream.pipe(file)
+ let tmpname = name + '.tmp-'+String(Math.random()).replace(/^0\./, '');
+ let file = fs.createWriteStream(tmpname);
+ let opened = false;
+ stream.pipe(file);
stream.done = function() {
function onend() {
file.on('close', function() {
renameTmp(tmpname, name, function(err) {
if (err) {
- stream.emit('error', err)
+ stream.emit('error', err);
} else {
- stream.emit('success')
+ stream.emit('success');
}
- })
- })
- file.destroySoon()
+ });
+ });
+ file.destroySoon();
}
if (_ended) {
- onend()
+ onend();
} else {
- stream.on('end', onend)
+ stream.on('end', onend);
}
- }
+ };
stream.abort = function() {
if (opened) {
- opened = false
+ opened = false;
file.on('close', function() {
- fs.unlink(tmpname, function(){})
- })
+ fs.unlink(tmpname, function() {});
+ });
}
- file.destroySoon()
- }
+ file.destroySoon();
+ };
file.on('open', function() {
- opened = true
+ opened = true;
// re-emitting open because it's handled in storage.js
- stream.emit('open')
- })
+ stream.emit('open');
+ });
file.on('error', function(err) {
- stream.emit('error', err)
- })
- })
- return stream
+ stream.emit('error', err);
+ });
+ });
+ return stream;
}
function read_stream(name, stream, callback) {
- var rstream = fs.createReadStream(name)
+ let rstream = fs.createReadStream(name);
rstream.on('error', function(err) {
- stream.emit('error', err)
- })
+ stream.emit('error', err);
+ });
rstream.on('open', function(fd) {
fs.fstat(fd, function(err, stats) {
- if (err) return stream.emit('error', err)
- stream.emit('content-length', stats.size)
- stream.emit('open')
- rstream.pipe(stream)
- })
- })
+ if (err) return stream.emit('error', err);
+ stream.emit('content-length', stats.size);
+ stream.emit('open');
+ rstream.pipe(stream);
+ });
+ });
- stream = MyStreams.ReadTarballStream()
+ stream = MyStreams.ReadTarballStream();
stream.abort = function() {
- rstream.close()
- }
- return stream
+ rstream.close();
+ };
+ return stream;
}
function create(name, contents, callback) {
fs.exists(name, function(exists) {
- if (exists) return callback( FSError('EEXISTS') )
- write(name, contents, callback)
- })
+ if (exists) return callback( FSError('EEXISTS') );
+ write(name, contents, callback);
+ });
}
function update(name, contents, callback) {
fs.exists(name, function(exists) {
- if (!exists) return callback( FSError('ENOENT') )
- write(name, contents, callback)
- })
+ if (!exists) return callback( FSError('ENOENT') );
+ write(name, contents, callback);
+ });
}
function read(name, callback) {
- fs.readFile(name, callback)
+ fs.readFile(name, callback);
}
-module.exports.read = read
+module.exports.read = read;
module.exports.read_json = function(name, cb) {
read(name, function(err, res) {
- if (err) return cb(err)
+ if (err) return cb(err);
- var args = []
+ let args = [];
try {
- args = [ null, JSON.parse(res.toString('utf8')) ]
+ args = [null, JSON.parse(res.toString('utf8'))];
} catch(err) {
- args = [ err ]
+ args = [err];
}
- cb.apply(null, args)
- })
-}
+ cb.apply(null, args);
+ });
+};
module.exports.lock_and_read = function(name, cb) {
locker.readFile(name, {lock: true}, function(err, res) {
- if (err) return cb(err)
- return cb(null, res)
- })
-}
+ if (err) return cb(err);
+ return cb(null, res);
+ });
+};
module.exports.lock_and_read_json = function(name, cb) {
locker.readFile(name, {lock: true, parse: true}, function(err, res) {
- if (err) return cb(err)
+ if (err) return cb(err);
return cb(null, res);
- })
-}
+ });
+};
-module.exports.unlock_file = function (name, cb) {
- locker.unlockFile(name, cb)
-}
+module.exports.unlock_file = function(name, cb) {
+ locker.unlockFile(name, cb);
+};
-module.exports.create = create
+module.exports.create = create;
module.exports.create_json = function(name, value, cb) {
- create(name, JSON.stringify(value, null, '\t'), cb)
-}
+ create(name, JSON.stringify(value, null, '\t'), cb);
+};
-module.exports.update = update
+module.exports.update = update;
module.exports.update_json = function(name, value, cb) {
- update(name, JSON.stringify(value, null, '\t'), cb)
-}
+ update(name, JSON.stringify(value, null, '\t'), cb);
+};
-module.exports.write = write
+module.exports.write = write;
module.exports.write_json = function(name, value, cb) {
- write(name, JSON.stringify(value, null, '\t'), cb)
-}
+ write(name, JSON.stringify(value, null, '\t'), cb);
+};
-module.exports.write_stream = write_stream
+module.exports.write_stream = write_stream;
-module.exports.read_stream = read_stream
+module.exports.read_stream = read_stream;
-module.exports.unlink = fs.unlink
+module.exports.unlink = fs.unlink;
-module.exports.rmdir = fs.rmdir
+module.exports.rmdir = fs.rmdir;
diff --git a/lib/local-storage.js b/lib/local-storage.js
index 5e42700b8..b9b227b58 100644
--- a/lib/local-storage.js
+++ b/lib/local-storage.js
@@ -1,697 +1,789 @@
-var assert = require('assert')
-var async = require('async')
-var Crypto = require('crypto')
-var fs = require('fs')
-var Error = require('http-errors')
-var Path = require('path')
-var Stream = require('readable-stream')
-var URL = require('url')
-var fs_storage = require('./local-fs')
-var Logger = require('./logger')
-var Search = require('./search')
-var MyStreams = require('./streams')
-var Utils = require('./utils')
-var info_file = 'package.json'
+'use strict';
-//
-// Implements Storage interface
-// (same for storage.js, local-storage.js, up-storage.js)
-//
-function Storage(config) {
- var self = Object.create(Storage.prototype)
- self.config = config
- self.logger = Logger.logger.child({ sub: 'fs' })
- return self
-}
+const assert = require('assert');
+const async = require('async');
+const Crypto = require('crypto');
+const fs = require('fs');
+const Error = require('http-errors');
+const Path = require('path');
+const Stream = require('readable-stream');
+const URL = require('url');
+const fs_storage = require('./local-fs');
+const Logger = require('./logger');
+const Search = require('./search');
+const MyStreams = require('./streams');
+const Utils = require('./utils');
+const info_file = 'package.json';
// returns the minimal package file
function get_boilerplate(name) {
return {
// standard things
- name: name,
- versions: {},
+ 'name': name,
+ 'versions': {},
'dist-tags': {},
// our own object
'_distfiles': {},
'_attachments': {},
'_uplinks': {},
- }
+ };
}
-Storage.prototype._internal_error = function(err, file, message) {
- this.logger.error( { err: err, file: file }
- , message + ' @{file}: @{!err.message}' )
- return Error[500]()
-}
-
-Storage.prototype.add_package = function(name, info, callback) {
- var storage = this.storage(name)
- if (!storage) return callback( Error[404]('this package cannot be added') )
-
- storage.create_json(info_file, get_boilerplate(name), function(err) {
- if (err && err.code === 'EEXISTS') {
- return callback( Error[409]('this package is already present') )
- }
-
- var latest = info['dist-tags'].latest
- if (latest && info.versions[latest]) {
- Search.add(info.versions[latest])
- }
- callback()
- })
-}
-
-Storage.prototype.remove_package = function(name, callback) {
- var self = this
- self.logger.info( { name: name }
- , 'unpublishing @{name} (all)')
-
- var storage = self.storage(name)
- if (!storage) return callback( Error[404]('no such package available') )
-
- storage.read_json(info_file, function(err, data) {
- if (err) {
- if (err.code === 'ENOENT') {
- return callback( Error[404]('no such package available') )
- } else {
- return callback(err)
- }
- }
- self._normalize_package(data)
-
- storage.unlink(info_file, function(err) {
- if (err) return callback(err)
-
- var files = Object.keys(data._attachments)
-
- function unlinkNext(cb) {
- if (files.length === 0) return cb()
-
- var file = files.shift()
- storage.unlink(file, function() {
- unlinkNext(cb)
- })
- }
-
- unlinkNext(function() {
- // try to unlink the directory, but ignore errors because it can fail
- storage.rmdir('.', function(err) {
- callback(err)
- })
- })
- })
- })
-
- Search.remove(name)
- this.config.localList.remove(name)
-}
-
-Storage.prototype._read_create_package = function(name, callback) {
- var self = this
- var storage = self.storage(name)
- if (!storage) {
- var data = get_boilerplate(name)
- self._normalize_package(data)
- return callback(null, data)
- }
- storage.read_json(info_file, function(err, data) {
- // TODO: race condition
- if (err) {
- if (err.code === 'ENOENT') {
- // if package doesn't exist, we create it here
- data = get_boilerplate(name)
- } else {
- return callback(self._internal_error(err, info_file, 'error reading'))
- }
- }
- self._normalize_package(data)
- callback(null, data)
- })
-}
-
-// synchronize remote package info with the local one
-// TODO: readfile called twice
-Storage.prototype.update_versions = function(name, newdata, callback) {
- var self = this
- self._read_create_package(name, function(err, data) {
- if (err) return callback(err)
-
- var change = false
- for (var ver in newdata.versions) {
- if (data.versions[ver] == null) {
- var verdata = newdata.versions[ver]
-
- // we don't keep readmes for package versions,
- // only one readme per package
- delete verdata.readme
-
- change = true
- data.versions[ver] = verdata
-
- if (verdata.dist && verdata.dist.tarball) {
- var filename = URL.parse(verdata.dist.tarball).pathname.replace(/^.*\//, '')
- // we do NOT overwrite any existing records
- if (data._distfiles[filename] == null) {
- var hash = data._distfiles[filename] = {
- url: verdata.dist.tarball,
- sha: verdata.dist.shasum,
- }
-
- if (verdata._verdaccio_uplink) {
- // if we got this information from a known registry,
- // use the same protocol for the tarball
- //
- // see https://github.com/rlidwka/sinopia/issues/166
- var tarball_url = URL.parse(hash.url)
- var uplink_url = URL.parse(self.config.uplinks[verdata._verdaccio_uplink].url)
- if (uplink_url.host === tarball_url.host) {
- tarball_url.protocol = uplink_url.protocol
- hash.registry = verdata._verdaccio_uplink
- hash.url = URL.format(tarball_url)
- }
- }
- }
- }
- }
- }
- for (var tag in newdata['dist-tags']) {
- if (!data['dist-tags'][tag] || data['dist-tags'][tag] !== newdata['dist-tags'][tag]) {
- change = true
- data['dist-tags'][tag] = newdata['dist-tags'][tag]
- }
- }
- for (var up in newdata._uplinks) {
- var need_change = !Utils.is_object(data._uplinks[up])
- || newdata._uplinks[up].etag !== data._uplinks[up].etag
- || newdata._uplinks[up].fetched !== data._uplinks[up].fetched
-
- if (need_change) {
- change = true
- data._uplinks[up] = newdata._uplinks[up]
- }
- }
- if (newdata.readme !== data.readme) {
- data.readme = newdata.readme
- change = true
- }
-
- if (change) {
- self.logger.debug('updating package info')
- self._write_package(name, data, function(err) {
- callback(err, data)
- })
- } else {
- callback(null, data)
- }
- })
-}
-
-Storage.prototype.add_version = function(name, version, metadata, tag, callback) {
- var self = this
- self.update_package(name, function updater(data, cb) {
- // keep only one readme per package
- data.readme = metadata.readme
- delete metadata.readme
-
- if (data.versions[version] != null) {
- return cb( Error[409]('this version already present') )
- }
-
- // if uploaded tarball has a different shasum, it's very likely that we have some kind of error
- if (Utils.is_object(metadata.dist) && typeof(metadata.dist.tarball) === 'string') {
- var tarball = metadata.dist.tarball.replace(/.*\//, '')
- if (Utils.is_object(data._attachments[tarball])) {
- if (data._attachments[tarball].shasum != null && metadata.dist.shasum != null) {
- if (data._attachments[tarball].shasum != metadata.dist.shasum) {
- return cb( Error[400]('shasum error, '
- + data._attachments[tarball].shasum
- + ' != ' + metadata.dist.shasum) )
- }
- }
-
- data._attachments[tarball].version = version
- }
- }
-
- data.versions[version] = metadata
- Utils.tag_version(data, version, tag)
- self.config.localList.add(name)
- cb()
- }, callback)
-}
-
-Storage.prototype.merge_tags = function(name, tags, callback) {
- var self = this
-
- self.update_package(name, function updater(data, cb) {
- for (var t in tags) {
- if (tags[t] === null) {
- delete data['dist-tags'][t]
- continue
- }
-
- if (data.versions[tags[t]] == null) {
- return cb( Error[404]("this version doesn't exist") )
- }
-
- Utils.tag_version(data, tags[t], t)
- }
- cb()
- }, callback)
-}
-
-Storage.prototype.replace_tags = function(name, tags, callback) {
- var self = this
-
- self.update_package(name, function updater(data, cb) {
- data['dist-tags'] = {}
-
- for (var t in tags) {
- if (tags[t] === null) {
- delete data['dist-tags'][t]
- continue
- }
-
- if (data.versions[tags[t]] == null) {
- return cb( Error[404]("this version doesn't exist") )
- }
-
- Utils.tag_version(data, tags[t], t)
- }
- cb()
- }, callback)
-}
-
-// currently supports unpublishing only
-Storage.prototype.change_package = function(name, metadata, revision, callback) {
- var self = this
-
- if (!Utils.is_object(metadata.versions) || !Utils.is_object(metadata['dist-tags'])) {
- return callback( Error[422]('bad data') )
+//
+// Implements Storage interface
+// (same for storage.js, local-storage.js, up-storage.js)
+//
+class Storage {
+ constructor(config) {
+ this.config = config;
+ this.logger = Logger.logger.child({sub: 'fs'});
}
- self.update_package(name, function updater(data, cb) {
- for (var ver in data.versions) {
- if (metadata.versions[ver] == null) {
- self.logger.info( { name: name, version: ver }
- , 'unpublishing @{name}@@{version}')
- delete data.versions[ver]
+ /**
+ *
+ * @param {*} err
+ * @param {*} file
+ * @param {*} message
+ */
+ _internal_error(err, file, message) {
+ this.logger.error( {err: err, file: file}
+ , message + ' @{file}: @{!err.message}' );
+ return Error[500]();
+ }
- for (var file in data._attachments) {
- if (data._attachments[file].version === ver) {
- delete data._attachments[file].version
- }
- }
+ /**
+ *
+ * @param {*} name
+ * @param {*} info
+ * @param {*} callback
+ */
+ add_package(name, info, callback) {
+ let storage = this.storage(name);
+ if (!storage) return callback( Error[404]('this package cannot be added') );
+
+ storage.create_json(info_file, get_boilerplate(name), function(err) {
+ if (err && err.code === 'EEXISTS') {
+ return callback( Error[409]('this package is already present') );
}
- }
- data['dist-tags'] = metadata['dist-tags']
- cb()
- }, function(err) {
- if (err) return callback(err)
- callback()
- })
-}
-Storage.prototype.remove_tarball = function(name, filename, revision, callback) {
- assert(Utils.validate_name(filename))
- var self = this
-
- self.update_package(name, function updater(data, cb) {
- if (data._attachments[filename]) {
- delete data._attachments[filename]
- cb()
- } else {
- cb(Error[404]('no such file available'))
- }
- }, function(err) {
- if (err) return callback(err)
- var storage = self.storage(name)
- if (storage) storage.unlink(filename, callback)
- })
-}
-
-Storage.prototype.add_tarball = function(name, filename) {
- assert(Utils.validate_name(filename))
-
- var stream = MyStreams.UploadTarballStream()
- var _transform = stream._transform
- var length = 0
- var shasum = Crypto.createHash('sha1')
-
- stream.abort = stream.done = function(){}
-
- stream._transform = function(data) {
- shasum.update(data)
- length += data.length
- _transform.apply(stream, arguments)
- }
-
- var self = this
- if (name === info_file || name === '__proto__') {
- process.nextTick(function() {
- stream.emit('error', Error[403]("can't use this filename"))
- })
- return stream
- }
-
- var storage = self.storage(name)
- if (!storage) {
- process.nextTick(function() {
- stream.emit('error', Error[404]("can't upload this package"))
- })
- return stream
- }
-
- var wstream = storage.write_stream(filename)
-
- wstream.on('error', function(err) {
- if (err.code === 'EEXISTS') {
- stream.emit('error', Error[409]('this tarball is already present'))
- } else if (err.code === 'ENOENT') {
- // check if package exists to throw an appropriate message
- self.get_package(name, function(_err, res) {
- if (_err) {
- stream.emit('error', _err)
- } else {
- stream.emit('error', err)
- }
- })
- } else {
- stream.emit('error', err)
- }
- })
-
- wstream.on('open', function() {
- // re-emitting open because it's handled in storage.js
- stream.emit('open')
- })
- wstream.on('success', function() {
- self.update_package(name, function updater(data, cb) {
- data._attachments[filename] = {
- shasum: shasum.digest('hex'),
+ let latest = info['dist-tags'].latest;
+ if (latest && info.versions[latest]) {
+ Search.add(info.versions[latest]);
}
- cb()
- }, function(err) {
+ callback();
+ });
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} callback
+ */
+ remove_package(name, callback) {
+ this.logger.info( {name: name}
+ , 'unpublishing @{name} (all)');
+
+ let storage = this.storage(name);
+ if (!storage) return callback( Error[404]('no such package available') );
+
+ storage.read_json(info_file, (err, data) => {
if (err) {
- stream.emit('error', err)
- } else {
- stream.emit('success')
- }
- })
- })
- stream.abort = function() {
- wstream.abort()
- }
- stream.done = function() {
- if (!length) {
- stream.emit('error', Error[422]('refusing to accept zero-length file'))
- wstream.abort()
- } else {
- wstream.done()
- }
- }
- stream.pipe(wstream)
-
- return stream
-}
-
-Storage.prototype.get_tarball = function(name, filename, callback) {
- assert(Utils.validate_name(filename))
- var self = this
-
- var stream = MyStreams.ReadTarballStream()
- stream.abort = function() {
- if (rstream) rstream.abort()
- }
-
- var storage = self.storage(name)
- if (!storage) {
- process.nextTick(function() {
- stream.emit('error', Error[404]('no such file available'))
- })
- return stream
- }
-
- var rstream = storage.read_stream(filename)
- rstream.on('error', function(err) {
- if (err && err.code === 'ENOENT') {
- stream.emit('error', Error(404, 'no such file available'))
- } else {
- stream.emit('error', err)
- }
- })
- rstream.on('content-length', function(v) {
- stream.emit('content-length', v)
- })
- rstream.on('open', function() {
- // re-emitting open because it's handled in storage.js
- stream.emit('open')
- rstream.pipe(stream)
- })
- return stream
-}
-
-Storage.prototype.get_package = function(name, options, callback) {
- if (typeof(options) === 'function') callback = options, options = {}
-
- var self = this
- var storage = self.storage(name)
- if (!storage) return callback( Error[404]('no such package available') )
-
- storage.read_json(info_file, function(err, result) {
- if (err) {
- if (err.code === 'ENOENT') {
- return callback( Error[404]('no such package available') )
- } else {
- return callback(self._internal_error(err, info_file, 'error reading'))
- }
- }
- self._normalize_package(result)
- callback(err, result)
- })
-}
-
-// walks through each package and calls `on_package` on them
-Storage.prototype._each_package = function (on_package, on_end) {
- var self = this
- var storages = {}
-
- storages[self.config.storage] = true
-
- if (self.config.packages) {
- Object.keys(self.config.packages || {}).map(function (pkg) {
- if (self.config.packages[pkg].storage) {
- storages[self.config.packages[pkg].storage] = true
- }
- })
- }
-
- var base = Path.dirname(self.config.self_path);
-
- async.eachSeries(Object.keys(storages), function (storage, cb) {
- fs.readdir(Path.resolve(base, storage), function (err, files) {
- if (err) return cb(err)
-
- async.eachSeries(files, function (file, cb) {
- if (file.match(/^@/)) {
- // scoped
- fs.readdir(Path.resolve(base, storage, file), function (err, files) {
- if (err) return cb(err)
-
- async.eachSeries(files, function (file2, cb) {
- if (Utils.validate_name(file2)) {
- on_package({
- name: file + '/' + file2,
- path: Path.resolve(base, storage, file, file2),
- }, cb)
- } else {
- cb()
- }
- }, cb)
- })
- } else if (Utils.validate_name(file)) {
- on_package({
- name: file,
- path: Path.resolve(base, storage, file)
- }, cb)
+ if (err.code === 'ENOENT') {
+ return callback( Error[404]('no such package available') );
} else {
- cb()
+ return callback(err);
}
- }, cb)
- })
- }, on_end)
-}
-
-//
-// This function allows to update the package thread-safely
-//
-// Arguments:
-// - name - package name
-// - updateFn - function(package, cb) - update function
-// - callback - callback that gets invoked after it's all updated
-//
-// Algorithm:
-// 1. lock package.json for writing
-// 2. read package.json
-// 3. updateFn(pkg, cb), and wait for cb
-// 4. write package.json.tmp
-// 5. move package.json.tmp package.json
-// 6. callback(err?)
-//
-Storage.prototype.update_package = function(name, updateFn, _callback) {
- var self = this
- var storage = self.storage(name)
- if (!storage) return _callback( Error[404]('no such package available') )
- storage.lock_and_read_json(info_file, function(err, json) {
- var locked = false
-
- // callback that cleans up lock first
- function callback(err) {
- var _args = arguments
- if (locked) {
- storage.unlock_file(info_file, function () {
- // ignore any error from the unlock
- _callback.apply(err, _args)
- })
- } else {
- _callback.apply(null, _args)
}
+ this._normalize_package(data);
+
+ storage.unlink(info_file, function(err) {
+ if (err) return callback(err);
+
+ let files = Object.keys(data._attachments);
+
+ function unlinkNext(cb) {
+ if (files.length === 0) return cb();
+
+ let file = files.shift();
+ storage.unlink(file, function() {
+ unlinkNext(cb);
+ });
+ }
+
+ unlinkNext(function() {
+ // try to unlink the directory, but ignore errors because it can fail
+ storage.rmdir('.', function(err) {
+ callback(err);
+ });
+ });
+ });
+ });
+
+ Search.remove(name);
+ this.config.localList.remove(name);
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} callback
+ */
+ _read_create_package(name, callback) {
+ let storage = this.storage(name);
+ if (!storage) {
+ let data = get_boilerplate(name);
+ this._normalize_package(data);
+ return callback(null, data);
+ }
+ storage.read_json(info_file, (err, data) => {
+ // TODO: race condition
+ if (err) {
+ if (err.code === 'ENOENT') {
+ // if package doesn't exist, we create it here
+ data = get_boilerplate(name);
+ } else {
+ return callback(this._internal_error(err, info_file, 'error reading'));
+ }
+ }
+ this._normalize_package(data);
+ callback(null, data);
+ });
+ }
+
+ /**
+ * Synchronize remote package info with the local one
+ * @param {*} name
+ * @param {*} newdata
+ * @param {*} callback
+ */
+ update_versions(name, newdata, callback) {
+ this._read_create_package(name, (err, data) => {
+ if (err) return callback(err);
+
+ let change = false;
+ for (let ver in newdata.versions) {
+ if (data.versions[ver] == null) {
+ let verdata = newdata.versions[ver];
+
+ // we don't keep readmes for package versions,
+ // only one readme per package
+ delete verdata.readme;
+
+ change = true;
+ data.versions[ver] = verdata;
+
+ if (verdata.dist && verdata.dist.tarball) {
+ let filename = URL.parse(verdata.dist.tarball).pathname.replace(/^.*\//, '');
+ // we do NOT overwrite any existing records
+ if (data._distfiles[filename] == null) {
+ let hash = data._distfiles[filename] = {
+ url: verdata.dist.tarball,
+ sha: verdata.dist.shasum,
+ };
+ // if (verdata[Symbol('_verdaccio_uplink')]) {
+ if (verdata._verdaccio_uplink) {
+ // if we got this information from a known registry,
+ // use the same protocol for the tarball
+ //
+ // see https://github.com/rlidwka/sinopia/issues/166
+ let tarball_url = URL.parse(hash.url);
+ let uplink_url = URL.parse(this.config.uplinks[verdata._verdaccio_uplink].url);
+ if (uplink_url.host === tarball_url.host) {
+ tarball_url.protocol = uplink_url.protocol;
+ hash.registry = verdata._verdaccio_uplink;
+ hash.url = URL.format(tarball_url);
+ }
+ }
+ }
+ }
+ }
+ }
+ for (let tag in newdata['dist-tags']) {
+ if (!data['dist-tags'][tag] || data['dist-tags'][tag] !== newdata['dist-tags'][tag]) {
+ change = true;
+ data['dist-tags'][tag] = newdata['dist-tags'][tag];
+ }
+ }
+ for (let up in newdata._uplinks) {
+ let need_change = !Utils.is_object(data._uplinks[up])
+ || newdata._uplinks[up].etag !== data._uplinks[up].etag
+ || newdata._uplinks[up].fetched !== data._uplinks[up].fetched;
+
+ if (need_change) {
+ change = true;
+ data._uplinks[up] = newdata._uplinks[up];
+ }
+ }
+ if (newdata.readme !== data.readme) {
+ data.readme = newdata.readme;
+ change = true;
+ }
+
+ if (change) {
+ this.logger.debug('updating package info');
+ this._write_package(name, data, function(err) {
+ callback(err, data);
+ });
+ } else {
+ callback(null, data);
+ }
+ });
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} version
+ * @param {*} metadata
+ * @param {*} tag
+ * @param {*} callback
+ */
+ add_version(name, version, metadata, tag, callback) {
+ this.update_package(name, (data, cb) => {
+ // keep only one readme per package
+ data.readme = metadata.readme;
+ delete metadata.readme;
+
+ if (data.versions[version] != null) {
+ return cb( Error[409]('this version already present') );
+ }
+
+ // if uploaded tarball has a different shasum, it's very likely that we have some kind of error
+ if (Utils.is_object(metadata.dist) && typeof(metadata.dist.tarball) === 'string') {
+ let tarball = metadata.dist.tarball.replace(/.*\//, '');
+ if (Utils.is_object(data._attachments[tarball])) {
+ if (data._attachments[tarball].shasum != null && metadata.dist.shasum != null) {
+ if (data._attachments[tarball].shasum != metadata.dist.shasum) {
+ return cb( Error[400]('shasum error, '
+ + data._attachments[tarball].shasum
+ + ' != ' + metadata.dist.shasum) );
+ }
+ }
+ data._attachments[tarball].version = version;
+ }
+ }
+
+ data.versions[version] = metadata;
+ Utils.tag_version(data, version, tag);
+ this.config.localList.add(name);
+ cb();
+ }, callback);
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} tags
+ * @param {*} callback
+ */
+ merge_tags(name, tags, callback) {
+ this.update_package(name, function updater(data, cb) {
+ for (let t in tags) {
+ if (tags[t] === null) {
+ delete data['dist-tags'][t];
+ continue;
+ }
+
+ if (data.versions[tags[t]] == null) {
+ return cb( Error[404]('this version doesn\'t exist') );
+ }
+
+ Utils.tag_version(data, tags[t], t);
+ }
+ cb();
+ }, callback);
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} tags
+ * @param {*} callback
+ */
+ replace_tags(name, tags, callback) {
+ this.update_package(name, function updater(data, cb) {
+ data['dist-tags'] = {};
+
+ for (let t in tags) {
+ if (tags[t] === null) {
+ delete data['dist-tags'][t];
+ continue;
+ }
+
+ if (data.versions[tags[t]] == null) {
+ return cb( Error[404]('this version doesn\'t exist') );
+ }
+
+ Utils.tag_version(data, tags[t], t);
+ }
+ cb();
+ }, callback);
+ }
+
+ /**
+ * Currently supports unpublishing only
+ * @param {*} name
+ * @param {*} metadata
+ * @param {*} revision
+ * @param {*} callback
+ */
+ change_package(name, metadata, revision, callback) {
+ if (!Utils.is_object(metadata.versions) || !Utils.is_object(metadata['dist-tags'])) {
+ return callback( Error[422]('bad data') );
}
- if (!err) {
- locked = true
+ this.update_package(name, (data, cb) => {
+ for (let ver in data.versions) {
+ if (metadata.versions[ver] == null) {
+ this.logger.info( {name: name, version: ver}
+ , 'unpublishing @{name}@@{version}');
+ delete data.versions[ver];
+
+ for (let file in data._attachments) {
+ if (data._attachments[file].version === ver) {
+ delete data._attachments[file].version;
+ }
+ }
+ }
+ }
+ data['dist-tags'] = metadata['dist-tags'];
+ cb();
+ }, function(err) {
+ if (err) return callback(err);
+ callback();
+ });
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} filename
+ * @param {*} revision
+ * @param {*} callback
+ */
+ remove_tarball(name, filename, revision, callback) {
+ assert(Utils.validate_name(filename));
+
+ this.update_package(name, (data, cb) => {
+ if (data._attachments[filename]) {
+ delete data._attachments[filename];
+ cb();
+ } else {
+ cb(Error[404]('no such file available'));
+ }
+ }, function(err) {
+ if (err) return callback(err);
+ let storage = this.storage(name);
+ if (storage) storage.unlink(filename, callback);
+ });
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} filename
+ */
+ add_tarball(name, filename) {
+ assert(Utils.validate_name(filename));
+
+ let stream = MyStreams.UploadTarballStream();
+ let _transform = stream._transform;
+ let length = 0;
+ let shasum = Crypto.createHash('sha1');
+
+ stream.abort = stream.done = function() {};
+
+ stream._transform = function(data) {
+ shasum.update(data);
+ length += data.length;
+ _transform.apply(stream, arguments);
+ };
+
+ if (name === info_file || name === '__proto__') {
+ process.nextTick(function() {
+ stream.emit('error', Error[403]('can\'t use this filename'));
+ });
+ return stream;
}
- if (err) {
- if (err.code === 'EAGAIN') {
- return callback( Error[503]('resource temporarily unavailable') )
+ let storage = this.storage(name);
+ if (!storage) {
+ process.nextTick(function() {
+ stream.emit('error', Error[404]('can\'t upload this package'));
+ });
+ return stream;
+ }
+
+ let wstream = storage.write_stream(filename);
+
+ wstream.on('error', (err) => {
+ if (err.code === 'EEXISTS') {
+ stream.emit('error', Error[409]('this tarball is already present'));
} else if (err.code === 'ENOENT') {
- return callback( Error[404]('no such package available') )
+ // check if package exists to throw an appropriate message
+ this.get_package(name, function(_err, res) {
+ if (_err) {
+ stream.emit('error', _err);
+ } else {
+ stream.emit('error', err);
+ }
+ });
} else {
- return callback(err)
+ stream.emit('error', err);
}
+ });
+
+ wstream.on('open', function() {
+ // re-emitting open because it's handled in storage.js
+ stream.emit('open');
+ });
+ wstream.on('success', () => {
+ this.update_package(name, function updater(data, cb) {
+ data._attachments[filename] = {
+ shasum: shasum.digest('hex'),
+ };
+ cb();
+ }, function(err) {
+ if (err) {
+ stream.emit('error', err);
+ } else {
+ stream.emit('success');
+ }
+ });
+ });
+ stream.abort = function() {
+ wstream.abort();
+ };
+ stream.done = function() {
+ if (!length) {
+ stream.emit('error', Error[422]('refusing to accept zero-length file'));
+ wstream.abort();
+ } else {
+ wstream.done();
+ }
+ };
+ stream.pipe(wstream);
+
+ return stream;
+ }
+
+ /**
+ *
+ * @param {*} name
+ * @param {*} filename
+ * @param {*} callback
+ */
+ get_tarball(name, filename, callback) {
+ assert(Utils.validate_name(filename));
+ let self = this;
+
+ let stream = MyStreams.ReadTarballStream();
+ stream.abort = function() {
+ if (rstream) rstream.abort();
+ };
+
+ let storage = self.storage(name);
+ if (!storage) {
+ process.nextTick(function() {
+ stream.emit('error', Error[404]('no such file available'));
+ });
+ return stream;
}
- self._normalize_package(json)
- updateFn(json, function(err) {
- if (err) return callback(err)
+ var rstream = storage.read_stream(filename);
+ rstream.on('error', function(err) {
+ if (err && err.code === 'ENOENT') {
+ stream.emit('error', Error(404, 'no such file available'));
+ } else {
+ stream.emit('error', err);
+ }
+ });
+ rstream.on('content-length', function(v) {
+ stream.emit('content-length', v);
+ });
+ rstream.on('open', function() {
+ // re-emitting open because it's handled in storage.js
+ stream.emit('open');
+ rstream.pipe(stream);
+ });
+ return stream;
+ }
- self._write_package(name, json, callback)
- })
- })
-}
+ /**
+ *
+ * @param {*} name
+ * @param {*} options
+ * @param {*} callback
+ */
+ get_package(name, options, callback) {
+ if (typeof(options) === 'function') {
+ callback = options, options = {};
+ }
-Storage.prototype.search = function(startkey, options) {
- var self = this
+ let storage = this.storage(name);
+ if (!storage) return callback( Error[404]('no such package available') );
- var stream = new Stream.PassThrough({ objectMode: true })
+ storage.read_json(info_file, (err, result) => {
+ if (err) {
+ if (err.code === 'ENOENT') {
+ return callback( Error[404]('no such package available') );
+ } else {
+ return callback(this._internal_error(err, info_file, 'error reading'));
+ }
+ }
+ this._normalize_package(result);
+ callback(err, result);
+ });
+ }
- self._each_package(function on_package(item, cb) {
- fs.stat(item.path, function(err, stats) {
- if (err) return cb(err)
+ /**
+ * Walks through each package and calls `on_package` on them
+ * @param {*} on_package
+ * @param {*} on_end
+ */
+ _each_package(on_package, on_end) {
+ let storages = {};
- if (stats.mtime > startkey) {
- self.get_package(item.name, options, function(err, data) {
- if (err) return cb(err)
+ storages[this.config.storage] = true;
- var versions = Utils.semver_sort(Object.keys(data.versions))
- var latest = data['dist-tags'] && data['dist-tags'].latest ? data['dist-tags'].latest : versions.pop()
+ if (this.config.packages) {
+ Object.keys(this.packages || {}).map( (pkg) => {
+ if (this.config.packages[pkg].storage) {
+ storages[this.config.packages[pkg].storage] = true;
+ }
+ });
+ }
+ const base = Path.dirname(this.config.self_path);
- if (data.versions[latest]) {
- stream.push({
- name : data.versions[latest].name,
- description : data.versions[latest].description,
- 'dist-tags' : { latest: latest },
- maintainers : data.versions[latest].maintainers ||
- [ data.versions[latest].author ].filter(Boolean),
- author : data.versions[latest].author,
- repository : data.versions[latest].repository,
- readmeFilename : data.versions[latest].readmeFilename || '',
- homepage : data.versions[latest].homepage,
- keywords : data.versions[latest].keywords,
- bugs : data.versions[latest].bugs,
- license : data.versions[latest].license,
- time : { modified: item.time ? new Date(item.time).toISOString() : undefined },
- versions : {},
- })
+ async.eachSeries(Object.keys(storages), function(storage, cb) {
+ fs.readdir(Path.resolve(base, storage), function(err, files) {
+ if (err) return cb(err);
+
+ async.eachSeries(files, function(file, cb) {
+ if (file.match(/^@/)) {
+ // scoped
+ fs.readdir(Path.resolve(base, storage, file), function(err, files) {
+ if (err) return cb(err);
+
+ async.eachSeries(files, function(file2, cb) {
+ if (Utils.validate_name(file2)) {
+ on_package({
+ name: `${file}/${file2}`,
+ path: Path.resolve(base, storage, file, file2),
+ }, cb);
+ } else {
+ cb();
+ }
+ }, cb);
+ });
+ } else if (Utils.validate_name(file)) {
+ on_package({
+ name: file,
+ path: Path.resolve(base, storage, file),
+ }, cb);
+ } else {
+ cb();
+ }
+ }, cb);
+ });
+ }, on_end);
+ }
+
+ /**
+ * This function allows to update the package thread-safely
+ Algorithm:
+ 1. lock package.json for writing
+ 2. read package.json
+ 3. updateFn(pkg, cb), and wait for cb
+ 4. write package.json.tmp
+ 5. move package.json.tmp package.json
+ 6. callback(err?)
+ * @param {*} name package name
+ * @param {*} updateFn function(package, cb) - update function
+ * @param {*} _callback callback that gets invoked after it's all updated
+ */
+ update_package(name, updateFn, _callback) {
+ let self = this;
+ let storage = self.storage(name);
+ if (!storage) return _callback( Error[404]('no such package available') );
+ storage.lock_and_read_json(info_file, function(err, json) {
+ let locked = false;
+
+ // callback that cleans up lock first
+ function callback(err) {
+ let _args = arguments;
+ if (locked) {
+ storage.unlock_file(info_file, function() {
+ // ignore any error from the unlock
+ _callback.apply(err, _args);
+ });
+ } else {
+ _callback.apply(null, _args);
+ }
+ }
+
+ if (!err) {
+ locked = true;
+ }
+
+ if (err) {
+ if (err.code === 'EAGAIN') {
+ return callback( Error[503]('resource temporarily unavailable') );
+ } else if (err.code === 'ENOENT') {
+ return callback( Error[404]('no such package available') );
+ } else {
+ return callback(err);
+ }
+ }
+
+ self._normalize_package(json);
+ updateFn(json, function(err) {
+ if (err) return callback(err);
+
+ self._write_package(name, json, callback);
+ });
+ });
+ }
+
+ /**
+ *
+ * @param {*} startkey
+ * @param {*} options
+ */
+ search(startkey, options) {
+ const stream = new Stream.PassThrough({objectMode: true});
+
+ this._each_package((item, cb) => {
+ fs.stat(item.path, (err, stats) => {
+ if (err) {
+ return cb(err);
}
- cb()
- })
- } else {
- cb()
+ if (stats.mtime > startkey) {
+ this.get_package(item.name, options, function(err, data) {
+ if (err) {
+ return cb(err);
+ }
+
+ let versions = Utils.semver_sort(Object.keys(data.versions));
+ let latest = data['dist-tags'] && data['dist-tags'].latest ? data['dist-tags'].latest : versions.pop();
+
+ if (data.versions[latest]) {
+ stream.push({
+ 'name': data.versions[latest].name,
+ 'description': data.versions[latest].description,
+ 'dist-tags': {latest: latest},
+ 'maintainers': data.versions[latest].maintainers ||
+ [data.versions[latest].author].filter(Boolean),
+ 'author': data.versions[latest].author,
+ 'repository': data.versions[latest].repository,
+ 'readmeFilename': data.versions[latest].readmeFilename || '',
+ 'homepage': data.versions[latest].homepage,
+ 'keywords': data.versions[latest].keywords,
+ 'bugs': data.versions[latest].bugs,
+ 'license': data.versions[latest].license,
+ 'time': {
+ modified: item.time ? new Date(item.time).toISOString() : undefined,
+ },
+ 'versions': {},
+ });
+ }
+
+ cb();
+ });
+ } else {
+ cb();
+ }
+ });
+ }, function on_end(err) {
+ if (err) return stream.emit('error', err);
+ stream.end();
+ });
+
+ return stream;
+ }
+
+ /**
+ *
+ * @param {*} pkg
+ */
+ _normalize_package(pkg) {
+ ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks'].forEach(function(key) {
+ if (!Utils.is_object(pkg[key])) pkg[key] = {};
+ });
+ if (typeof(pkg._rev) !== 'string') {
+ pkg._rev = '0-0000000000000000';
}
- })
- }, function on_end(err) {
- if (err) return stream.emit('error', err)
- stream.end()
- })
+ // normalize dist-tags
+ Utils.normalize_dist_tags(pkg);
+ }
- return stream
-}
+ /**
+ *
+ * @param {*} name
+ * @param {*} json
+ * @param {*} callback
+ */
+ _write_package(name, json, callback) {
+ // calculate revision a la couchdb
+ if (typeof(json._rev) !== 'string') {
+ json._rev = '0-0000000000000000';
+ }
+ let rev = json._rev.split('-');
+ json._rev = ((+rev[0] || 0) + 1) + '-' + Crypto.pseudoRandomBytes(8).toString('hex');
-Storage.prototype._normalize_package = function(pkg) {
- ;['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks'].forEach(function(key) {
- if (!Utils.is_object(pkg[key])) pkg[key] = {}
- })
- if (typeof(pkg._rev) !== 'string') pkg._rev = '0-0000000000000000'
+ let storage = this.storage(name);
+ if (!storage) return callback();
+ storage.write_json(info_file, json, callback);
+ }
- // normalize dist-tags
- Utils.normalize_dist_tags(pkg)
-}
-
-Storage.prototype._write_package = function(name, json, callback) {
-
- // calculate revision a la couchdb
- if (typeof(json._rev) !== 'string') json._rev = '0-0000000000000000'
- var rev = json._rev.split('-')
- json._rev = ((+rev[0] || 0) + 1) + '-' + Crypto.pseudoRandomBytes(8).toString('hex')
-
- var storage = this.storage(name)
- if (!storage) return callback()
- storage.write_json(info_file, json, callback)
-}
-
-Storage.prototype.storage = function(package) {
- var path = this.config.get_package_spec(package).storage
- if (path == null) path = this.config.storage
- if (path == null || path === false) {
- this.logger.debug( { name: package }
- , 'this package has no storage defined: @{name}' )
- return null
- }
- return Path_Wrapper(
- Path.join(
- Path.resolve(Path.dirname(this.config.self_path || ''), path),
- package
- )
- )
+ /**
+ *
+ * @param {*} pkg
+ */
+ storage(pkg) {
+ let path = this.config.get_package_spec(pkg).storage;
+ if (path == null) {
+ path = this.config.storage;
+ }
+ if (path == null || path === false) {
+ this.logger.debug( {name: pkg}
+ , 'this package has no storage defined: @{name}' );
+ return null;
+ }
+ return Path_Wrapper(
+ Path.join(
+ Path.resolve(Path.dirname(this.config.self_path || ''), path),
+ pkg
+ )
+ );
+ }
}
var Path_Wrapper = (function() {
// a wrapper adding paths to fs_storage methods
function Wrapper(path) {
- var self = Object.create(Wrapper.prototype)
- self.path = path
- return self
+ let self = Object.create(Wrapper.prototype);
+ self.path = path;
+ return self;
}
- for (var i in fs_storage) {
+ for (let i in fs_storage) {
if (fs_storage.hasOwnProperty(i)) {
- Wrapper.prototype[i] = wrapper(i)
+ Wrapper.prototype[i] = wrapper(i);
}
}
function wrapper(method) {
- return function(/*...*/) {
- var args = Array.prototype.slice.apply(arguments)
- args[0] = Path.join(this.path, args[0] || '')
- return fs_storage[method].apply(null, args)
- }
+ return function(/* ...*/) {
+ let args = Array.prototype.slice.apply(arguments);
+ args[0] = Path.join(this.path, args[0] || '');
+ return fs_storage[method].apply(null, args);
+ };
}
- return Wrapper
-})()
+ return Wrapper;
+})();
-module.exports = Storage
+module.exports = Storage;
diff --git a/lib/logger.js b/lib/logger.js
index 78a753667..fa68c8b47 100644
--- a/lib/logger.js
+++ b/lib/logger.js
@@ -1,157 +1,178 @@
-var Logger = require('bunyan')
-var Error = require('http-errors')
-var Stream = require('stream')
-var Utils = require('./utils')
+'use strict';
+const Logger = require('bunyan');
+const Error = require('http-errors');
+const Stream = require('stream');
+const chalk = require('chalk');
+const Utils = require('./utils');
+const pkgJSON = require('../package.json');
+
+/**
+ *
+ * @param {*} x
+ */
function getlvl(x) {
- switch(true) {
- case x < 15 : return 'trace'
- case x < 25 : return 'debug'
- case x < 35 : return 'info'
- case x == 35 : return 'http'
- case x < 45 : return 'warn'
- case x < 55 : return 'error'
- default : return 'fatal'
- }
+ switch(true) {
+ case x < 15 : return 'trace';
+ case x < 25 : return 'debug';
+ case x < 35 : return 'info';
+ case x == 35 : return 'http';
+ case x < 45 : return 'warn';
+ case x < 55 : return 'error';
+ default : return 'fatal';
+ }
}
module.exports.setup = function(logs) {
- var streams = []
- if (logs == null) logs = [{ type: 'stdout', format: 'pretty', level: 'http' }]
+ let streams = [];
+ if (logs == null) logs = [{type: 'stdout', format: 'pretty', level: 'http'}];
- logs.forEach(function(target) {
- var stream = new Stream()
- stream.writable = true
+ logs.forEach(function(target) {
+ const stream = new Stream();
+ stream.writable = true;
- if (target.type === 'stdout' || target.type === 'stderr') {
- // destination stream
- var dest = target.type === 'stdout' ? process.stdout : process.stderr
+ if (target.type === 'stdout' || target.type === 'stderr') {
+ // destination stream
+ const dest = target.type === 'stdout' ? process.stdout : process.stderr;
- if (target.format === 'pretty') {
- // making fake stream for prettypritting
- stream.write = function(obj) {
- dest.write(print(obj.level, obj.msg, obj, dest.isTTY) + '\n')
- }
- } else if (target.format === 'pretty-timestamped') {
- // making fake stream for prettypritting
- stream.write = function(obj) {
- dest.write(obj.time.toISOString() + print(obj.level, obj.msg, obj, dest.isTTY) + '\n')
- }
- } else {
- stream.write = function(obj) {
- dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n')
- }
- }
- } else if (target.type === 'file') {
- var dest = require('fs').createWriteStream(target.path, {flags: 'a', encoding: 'utf8'})
- dest.on('error', function (err) {
- Logger.emit('error', err)
- })
- stream.write = function(obj) {
- if (target.format === 'pretty') {
- dest.write(print(obj.level, obj.msg, obj, false) + '\n')
- } else {
- dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n')
- }
- }
- } else {
- throw Error('wrong target type for a log')
- }
+ if (target.format === 'pretty') {
+ // making fake stream for prettypritting
+ stream.write = function(obj) {
+ dest.write(print(obj.level, obj.msg, obj, dest.isTTY) + '\n');
+ };
+ } else if (target.format === 'pretty-timestamped') {
+ // making fake stream for prettypritting
+ stream.write = function(obj) {
+ dest.write(obj.time.toISOString() + print(obj.level, obj.msg, obj, dest.isTTY) + '\n');
+ };
+ } else {
+ stream.write = function(obj) {
+ dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n');
+ };
+ }
+ } else if (target.type === 'file') {
+ const dest = require('fs').createWriteStream(target.path, {flags: 'a', encoding: 'utf8'});
+ dest.on('error', function(err) {
+ Logger.emit('error', err);
+ });
+ stream.write = function(obj) {
+ if (target.format === 'pretty') {
+ dest.write(print(obj.level, obj.msg, obj, false) + '\n');
+ } else {
+ dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n');
+ }
+ };
+ } else {
+ throw Error('wrong target type for a log');
+ }
- if (target.level === 'http') target.level = 35
- streams.push({
- type: 'raw',
- level: target.level || 35,
- stream: stream,
- })
- })
+ if (target.level === 'http') target.level = 35;
+ streams.push({
+ type: 'raw',
+ level: target.level || 35,
+ stream: stream,
+ });
+ });
- var logger = new Logger({
- name: 'verdaccio',
- streams: streams,
- serializers: {
- err: Logger.stdSerializers.err,
- req: Logger.stdSerializers.req,
- res: Logger.stdSerializers.res,
- },
- })
+ let logger = new Logger({
+ name: pkgJSON.name,
+ streams: streams,
+ serializers: {
+ err: Logger.stdSerializers.err,
+ req: Logger.stdSerializers.req,
+ res: Logger.stdSerializers.res,
+ },
+ });
- module.exports.logger = logger
-}
+ module.exports.logger = logger;
+};
// adopted from socket.io
// this part was converted to coffee-script and back again over the years,
// so it might look weird
// level to color
-var levels = {
- fatal : 31,
- error : 31,
- warn : 33,
- http : 35,
- info : 36,
- debug : 90,
- trace : 90,
-}
-
-var max = 0
-for (var l in levels) {
- max = Math.max(max, l.length)
+let levels = {
+ fatal: chalk.red,
+ error: chalk.red,
+ warn: chalk.yellow,
+ http: chalk.magenta,
+ info: chalk.cyan,
+ debug: chalk.black,
+ trace: chalk.white,
+};
+
+let max = 0;
+for (let l in levels) {
+ max = Math.max(max, l.length);
}
+/**
+ *
+ * @param {*} str
+ */
function pad(str) {
- if (str.length < max) return str + ' '.repeat(max - str.length)
- return str
+ if (str.length < max) return str + ' '.repeat(max - str.length);
+ return str;
}
-var subsystems = [{
- in : '\033[32m<--\033[39m',
- out : '\033[33m-->\033[39m',
- fs : '\033[90m-=-\033[39m',
- default : '\033[34m---\033[39m',
-}, {
- in : '<--',
- out : '-->',
- fs : '-=-',
- default : '---',
-}]
-
+/**
+ * Build a string
+ * @param {*} type
+ * @param {*} msg
+ * @param {*} obj
+ * @param {*} colors
+ */
function print(type, msg, obj, colors) {
- if (typeof type === 'number') type = getlvl(type)
- var finalmsg = msg.replace(/@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g, function(_, name) {
- var str = obj, is_error
- if (name[0] === '!') {
- name = name.substr(1)
- is_error = true
- }
+ if (typeof type === 'number') type = getlvl(type);
+ let finalmsg = msg.replace(/@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g, function(_, name) {
+ let str = obj;
+ let is_error;
+ if (name[0] === '!') {
+ name = name.substr(1);
+ is_error = true;
+ }
- var _ref = name.split('.')
- for (var _i = 0; _i < _ref.length; _i++) {
- var id = _ref[_i]
- if (Utils.is_object(str) || Array.isArray(str)) {
- str = str[id]
- } else {
- str = undefined
- }
- }
+ let _ref = name.split('.');
+ for (let _i = 0; _i < _ref.length; _i++) {
+ let id = _ref[_i];
+ if (Utils.is_object(str) || Array.isArray(str)) {
+ str = str[id];
+ } else {
+ str = undefined;
+ }
+ }
- if (typeof(str) === 'string') {
- if (!colors || str.includes('\n')) {
- return str
- } else if (is_error) {
- return '\033[31m' + str + '\033[39m'
- } else {
- return '\033[32m' + str + '\033[39m'
- }
- } else {
- return require('util').inspect(str, null, null, colors)
- }
- })
+ if (typeof(str) === 'string') {
+ if (!colors || str.includes('\n')) {
+ return str;
+ } else if (is_error) {
+ return chalk.red(str);
+ } else {
+ return chalk.green(str);
+ }
+ } else {
+ return require('util').inspect(str, null, null, colors);
+ }
+ });
- var sub = subsystems[colors ? 0 : 1][obj.sub] || subsystems[+!colors].default
- if (colors) {
- return ' \033[' + levels[type] + 'm' + (pad(type)) + '\033[39m ' + sub + ' ' + finalmsg
- } else {
- return ' ' + (pad(type)) + ' ' + sub + ' ' + finalmsg
- }
+ const subsystems = [{
+ in: chalk.green('<--'),
+ out: chalk.yellow('-->'),
+ fs: chalk.black('-=-'),
+ default: chalk.blue('---'),
+ }, {
+ in: '<--',
+ out: '-->',
+ fs: '-=-',
+ default: '---',
+ }];
+
+ let sub = subsystems[colors ? 0 : 1][obj.sub] || subsystems[+!colors].default;
+ if (colors) {
+ // return ' \033[' + levels[type] + 'm' + (pad(type)) + '\033[39m ' + sub + ' ' + finalmsg
+ return ` ${levels[type]((pad(type)))}${chalk.white(`${sub} ${finalmsg}`)}`;
+ } else {
+ return ` ${(pad(type))}${sub} ${finalmsg}`;
+ }
}
diff --git a/lib/middleware.js b/lib/middleware.js
index 16a9ee34f..38f0a3963 100644
--- a/lib/middleware.js
+++ b/lib/middleware.js
@@ -1,79 +1,81 @@
-var crypto = require('crypto')
-var Error = require('http-errors')
-var utils = require('./utils')
-var Logger = require('./logger')
+'use strict';
+
+let crypto = require('crypto');
+let Error = require('http-errors');
+let utils = require('./utils');
+let Logger = require('./logger');
module.exports.match = function match(regexp) {
return function(req, res, next, value, name) {
if (regexp.exec(value)) {
- next()
+ next();
} else {
- next('route')
+ next('route');
}
- }
-}
+ };
+};
module.exports.validate_name = function validate_name(req, res, next, value, name) {
if (value.charAt(0) === '-') {
// special case in couchdb usually
- next('route')
+ next('route');
} else if (utils.validate_name(value)) {
- next()
+ next();
} else {
- next( Error[403]('invalid ' + name) )
+ next( Error[403]('invalid ' + name) );
}
-}
+};
module.exports.validate_package = function validate_package(req, res, next, value, name) {
if (value.charAt(0) === '-') {
// special case in couchdb usually
- next('route')
+ next('route');
} else if (utils.validate_package(value)) {
- next()
+ next();
} else {
- next( Error[403]('invalid ' + name) )
+ next( Error[403]('invalid ' + name) );
}
-}
+};
module.exports.media = function media(expect) {
return function(req, res, next) {
if (req.headers['content-type'] !== expect) {
next( Error[415]('wrong content-type, expect: ' + expect
- + ', got: '+req.headers['content-type']) )
+ + ', got: '+req.headers['content-type']) );
} else {
- next()
+ next();
}
- }
-}
+ };
+};
module.exports.expect_json = function expect_json(req, res, next) {
if (!utils.is_object(req.body)) {
- return next( Error[400]("can't parse incoming json") )
+ return next( Error[400]('can\'t parse incoming json') );
}
- next()
-}
+ next();
+};
module.exports.anti_loop = function(config) {
return function(req, res, next) {
if (req.headers.via != null) {
- var arr = req.headers.via.split(',')
+ let arr = req.headers.via.split(',');
- for (var i=0; i= 200 && res.statusCode < 300)) {
- res.header('ETag', '"' + md5sum(body) + '"')
+ res.header('ETag', '"' + md5sum(body) + '"');
}
} else {
// send(null), send(204), etc.
@@ -127,77 +129,77 @@ module.exports.final = function(body, req, res, next) {
// as an error handler, we can't report error properly,
// and should just close socket
if (err.message.match(/set headers after they are sent/)) {
- if (res.socket != null) res.socket.destroy()
- return
+ if (res.socket != null) res.socket.destroy();
+ return;
} else {
- throw err
+ throw err;
}
}
- res.send(body)
-}
+ res.send(body);
+};
module.exports.log = function(req, res, next) {
// logger
- req.log = Logger.logger.child({ sub: 'in' })
+ req.log = Logger.logger.child({sub: 'in'});
- var _auth = req.headers.authorization
- if (_auth != null) req.headers.authorization = ''
- var _cookie = req.headers.cookie
- if (_cookie != null) req.headers.cookie = ''
+ let _auth = req.headers.authorization;
+ if (_auth != null) req.headers.authorization = '';
+ let _cookie = req.headers.cookie;
+ if (_cookie != null) req.headers.cookie = '';
- req.url = req.originalUrl
- req.log.info( { req: req, ip: req.ip }
- , '@{ip} requested \'@{req.method} @{req.url}\'' )
- req.originalUrl = req.url
+ req.url = req.originalUrl;
+ req.log.info( {req: req, ip: req.ip}
+ , '@{ip} requested \'@{req.method} @{req.url}\'' );
+ req.originalUrl = req.url;
- if (_auth != null) req.headers.authorization = _auth
- if (_cookie != null) req.headers.cookie = _cookie
+ if (_auth != null) req.headers.authorization = _auth;
+ if (_cookie != null) req.headers.cookie = _cookie;
- var bytesin = 0
+ let bytesin = 0;
req.on('data', function(chunk) {
- bytesin += chunk.length
- })
+ bytesin += chunk.length;
+ });
- var bytesout = 0
- var _write = res.write
+ let bytesout = 0;
+ let _write = res.write;
res.write = function(buf) {
- bytesout += buf.length
- _write.apply(res, arguments)
- }
+ bytesout += buf.length;
+ _write.apply(res, arguments);
+ };
function log() {
- var message = "@{status}, user: @{user}, req: '@{request.method} @{request.url}'"
+ let message = '@{status}, user: @{user}, req: \'@{request.method} @{request.url}\'';
if (res._verdaccio_error) {
- message += ', error: @{!error}'
+ message += ', error: @{!error}';
} else {
- message += ', bytes: @{bytes.in}/@{bytes.out}'
+ message += ', bytes: @{bytes.in}/@{bytes.out}';
}
- req.url = req.originalUrl
+ req.url = req.originalUrl;
req.log.warn({
- request : { method: req.method, url: req.url },
- level : 35, // http
- user : req.remote_user && req.remote_user.name,
- status : res.statusCode,
- error : res._verdaccio_error,
- bytes : {
- in : bytesin,
- out : bytesout,
- }
- }, message)
- req.originalUrl = req.url
+ request: {method: req.method, url: req.url},
+ level: 35, // http
+ user: req.remote_user && req.remote_user.name,
+ status: res.statusCode,
+ error: res._verdaccio_error,
+ bytes: {
+ in: bytesin,
+ out: bytesout,
+ },
+ }, message);
+ req.originalUrl = req.url;
}
req.on('close', function() {
- log(true)
- })
+ log(true);
+ });
- var _end = res.end
+ let _end = res.end;
res.end = function(buf) {
- if (buf) bytesout += buf.length
- _end.apply(res, arguments)
- log()
- }
- next()
-}
+ if (buf) bytesout += buf.length;
+ _end.apply(res, arguments);
+ log();
+ };
+ next();
+};
diff --git a/lib/notify.js b/lib/notify.js
index c0658d0dd..59b2484d1 100644
--- a/lib/notify.js
+++ b/lib/notify.js
@@ -1,24 +1,24 @@
-var Handlebars = require('handlebars')
-var request = require('request')
-var Logger = require('./logger')
+'use strict';
+
+let Handlebars = require('handlebars');
+let request = require('request');
+let Logger = require('./logger');
module.exports.notify = function(metadata, config) {
-
if (config.notify && config.notify.content) {
+ let template = Handlebars.compile(config.notify.content);
+ let content = template( metadata );
- var template = Handlebars.compile(config.notify.content)
- var content = template( metadata )
-
- var options = {
- body: content
- }
+ let options = {
+ body: content,
+ };
// provides fallback support, it's accept an Object {} and Array of {}
if ( config.notify.headers && Array.isArray(config.notify.headers) ) {
- var header = {};
+ let header = {};
config.notify.headers.map(function(item) {
if (Object.is(item, item)) {
- for (var key in item) {
+ for (let key in item) {
header[key] = item[key];
}
}
@@ -31,19 +31,18 @@ module.exports.notify = function(metadata, config) {
options.method = config.notify.method;
if (config.notify.endpoint) {
- options.url = config.notify.endpoint
+ options.url = config.notify.endpoint;
}
request(options, function(err, response, body) {
if (err) {
- Logger.logger.error( { err: err }, ' notify error: @{err.message}' );
+ Logger.logger.error( {err: err}, ' notify error: @{err.message}' );
} else {
- Logger.logger.info({ content: content}, 'A notification has been shipped: @{content}')
+ Logger.logger.info({content: content}, 'A notification has been shipped: @{content}');
if (body) {
- Logger.logger.debug( { body: body }, ' body: @{body}' );
+ Logger.logger.debug( {body: body}, ' body: @{body}' );
}
}
});
-
}
-}
+};
diff --git a/lib/plugin-loader.js b/lib/plugin-loader.js
index 5e54110dd..6ff4739e2 100644
--- a/lib/plugin-loader.js
+++ b/lib/plugin-loader.js
@@ -1,57 +1,59 @@
-var Path = require('path')
+'use strict';
+
+let Path = require('path');
function try_load(path) {
try {
- return require(path)
+ return require(path);
} catch(err) {
if (err.code === 'MODULE_NOT_FOUND') {
- return null
+ return null;
}
- throw err
+ throw err;
}
}
function load_plugins(config, plugin_configs, params, sanity_check) {
- var plugins = Object.keys(plugin_configs || {}).map(function(p) {
- var plugin
+ let plugins = Object.keys(plugin_configs || {}).map(function(p) {
+ let plugin;
// try local plugins first
- plugin = try_load(Path.resolve(__dirname + '/plugins', p))
+ plugin = try_load(Path.resolve(__dirname + '/plugins', p));
// npm package
if (plugin === null && p.match(/^[^\.\/]/)) {
- plugin = try_load('verdaccio-' + p)
+ plugin = try_load(`verdaccio-${p}`);
// compatibility for old sinopia plugins
if (!plugin) {
- plugin = try_load('sinopia-' + p)
+ plugin = try_load(`sinopia-${p}`);
}
}
if (plugin === null) {
- plugin = try_load(p)
+ plugin = try_load(p);
}
// relative to config path
if (plugin === null && p.match(/^\.\.?($|\/)/)) {
- plugin = try_load(Path.resolve(Path.dirname(config.self_path), p))
+ plugin = try_load(Path.resolve(Path.dirname(config.self_path), p));
}
if (plugin === null) {
- throw new Error('"' + p + '" plugin not found\ntry "npm install verdaccio-' + p + '"')
+ throw Error('"' + p + '" plugin not found\ntry "npm install verdaccio-' + p + '"');
}
if (typeof(plugin) !== 'function')
- throw new Error('"' + p + '" doesn\'t look like a valid plugin')
+ throw Error('"' + p + '" doesn\'t look like a valid plugin');
- plugin = plugin(plugin_configs[p], params)
+ plugin = plugin(plugin_configs[p], params);
if (plugin === null || !sanity_check(plugin))
- throw new Error('"' + p + '" doesn\'t look like a valid plugin')
+ throw Error('"' + p + '" doesn\'t look like a valid plugin');
return plugin;
- })
+ });
- return plugins
+ return plugins;
}
exports.load_plugins = load_plugins;
diff --git a/lib/plugins/htpasswd/crypt3.js b/lib/plugins/htpasswd/crypt3.js
index d992bcc79..8c0e7a34d 100644
--- a/lib/plugins/htpasswd/crypt3.js
+++ b/lib/plugins/htpasswd/crypt3.js
@@ -1,3 +1,5 @@
+'use strict';
+
/** Node.js Crypt(3) Library
Inspired by (and intended to be compatible with) sendanor/crypt3
@@ -10,7 +12,7 @@
*/
-var crypt = require('unix-crypt-td-js'),
+let crypt = require('unix-crypt-td-js'),
crypto = require('crypto');
function createSalt(type) {
@@ -33,7 +35,6 @@ function createSalt(type) {
default:
throw new TypeError('Unknown salt type at crypt3.createSalt: ' + type);
}
-
}
function crypt3(key, salt) {
diff --git a/lib/plugins/htpasswd/index.js b/lib/plugins/htpasswd/index.js
index 69ea5fb48..dc34266b2 100644
--- a/lib/plugins/htpasswd/index.js
+++ b/lib/plugins/htpasswd/index.js
@@ -1,49 +1,51 @@
-var fs = require('fs')
-var Path = require('path')
-var utils = require('./utils')
+'use strict';
-module.exports = HTPasswd
+let fs = require('fs');
+let Path = require('path');
+let utils = require('./utils');
+
+module.exports = HTPasswd;
function HTPasswd(config, stuff) {
- var self = Object.create(HTPasswd.prototype)
- self._users = {}
+ let self = Object.create(HTPasswd.prototype);
+ self._users = {};
// config for this module
- self._config = config
+ self._config = config;
// verdaccio logger
- self._logger = stuff.logger
+ self._logger = stuff.logger;
// verdaccio main config object
- self._verdaccio_config = stuff.config
+ self._verdaccio_config = stuff.config;
// all this "verdaccio_config" stuff is for b/w compatibility only
- self._maxusers = self._config.max_users
- if (!self._maxusers) self._maxusers = self._verdaccio_config.max_users
+ self._maxusers = self._config.max_users;
+ if (!self._maxusers) self._maxusers = self._verdaccio_config.max_users;
// set maxusers to Infinity if not specified
- if (!self._maxusers) self._maxusers = Infinity
+ if (!self._maxusers) self._maxusers = Infinity;
- self._last_time = null
- var file = self._config.file
- if (!file) file = self._verdaccio_config.users_file
- if (!file) throw new Error('should specify "file" in config')
- self._path = Path.resolve(Path.dirname(self._verdaccio_config.self_path), file)
- return self
+ self._last_time = null;
+ let file = self._config.file;
+ if (!file) file = self._verdaccio_config.users_file;
+ if (!file) throw new Error('should specify "file" in config');
+ self._path = Path.resolve(Path.dirname(self._verdaccio_config.self_path), file);
+ return self;
}
-HTPasswd.prototype.authenticate = function (user, password, cb) {
- var self = this
- self._reload(function (err) {
- if (err) return cb(err.code === 'ENOENT' ? null : err)
- if (!self._users[user]) return cb(null, false)
- if (!utils.verify_password(user, password, self._users[user])) return cb(null, false)
+HTPasswd.prototype.authenticate = function(user, password, cb) {
+ let self = this;
+ self._reload(function(err) {
+ if (err) return cb(err.code === 'ENOENT' ? null : err);
+ if (!self._users[user]) return cb(null, false);
+ if (!utils.verify_password(user, password, self._users[user])) return cb(null, false);
// authentication succeeded!
// return all usergroups this user has access to;
// (this particular package has no concept of usergroups, so just return user herself)
- return cb(null, [user])
- })
-}
+ return cb(null, [user]);
+ });
+};
// hopefully race-condition-free way to add users:
// 1. lock file for writing (other processes can still read)
@@ -52,85 +54,82 @@ HTPasswd.prototype.authenticate = function (user, password, cb) {
// 4. move .htpasswd.tmp to .htpasswd
// 5. reload .htpasswd
// 6. unlock file
-HTPasswd.prototype.adduser = function (user, password, real_cb) {
- var self = this
+HTPasswd.prototype.adduser = function(user, password, real_cb) {
+ let self = this;
function sanity_check() {
- var err = null
+ let err = null;
if (self._users[user]) {
- err = Error('this user already exists')
+ err = Error('this user already exists');
} else if (Object.keys(self._users).length >= self._maxusers) {
- err = Error('maximum amount of users reached')
+ err = Error('maximum amount of users reached');
}
- if (err) err.status = 403
- return err
+ if (err) err.status = 403;
+ return err;
}
// preliminary checks, just to ensure that file won't be reloaded if it's not needed
- var s_err = sanity_check()
- if (s_err) return real_cb(s_err, false)
+ let s_err = sanity_check();
+ if (s_err) return real_cb(s_err, false);
- utils.lock_and_read(self._path, function (err, res) {
- var locked = false
+ utils.lock_and_read(self._path, function(err, res) {
+ let locked = false;
// callback that cleans up lock first
function cb(err) {
if (locked) {
- utils.unlock_file(self._path, function () {
+ utils.unlock_file(self._path, function() {
// ignore any error from the unlock
- real_cb(err, !err)
- })
+ real_cb(err, !err);
+ });
} else {
- real_cb(err, !err)
+ real_cb(err, !err);
}
}
if (!err) {
- locked = true
+ locked = true;
}
// ignore ENOENT errors, we'll just create .htpasswd in that case
- if (err && err.code !== 'ENOENT') return cb(err)
+ if (err && err.code !== 'ENOENT') return cb(err);
- var body = (res || '').toString('utf8')
- self._users = utils.parse_htpasswd(body)
+ let body = (res || '').toString('utf8');
+ self._users = utils.parse_htpasswd(body);
// real checks, to prevent race conditions
- var s_err = sanity_check()
- if (s_err) return cb(s_err)
+ let s_err = sanity_check();
+ if (s_err) return cb(s_err);
try {
- body = utils.add_user_to_htpasswd(body, user, password)
+ body = utils.add_user_to_htpasswd(body, user, password);
} catch (err) {
- return cb(err)
+ return cb(err);
}
- fs.writeFile(self._path, body, function (err) {
- if (err) return cb(err)
- self._reload(function () {
- cb(null, true)
- })
- })
- })
-}
-
-HTPasswd.prototype._reload = function (_callback) {
- var self = this
-
- fs.stat(self._path, function (err, stats) {
- if (err) return _callback(err)
-
- if (self._last_time === stats.mtime) return _callback()
- self._last_time = stats.mtime
-
- fs.readFile(self._path, 'utf8', function (err, buffer) {
- if (err) return _callback(err)
-
- self._users = utils.parse_htpasswd(buffer)
-
- _callback()
-
+ fs.writeFile(self._path, body, function(err) {
+ if (err) return cb(err);
+ self._reload(function() {
+ cb(null, true);
+ });
});
-
});
+};
-}
+HTPasswd.prototype._reload = function(_callback) {
+ let self = this;
+
+ fs.stat(self._path, function(err, stats) {
+ if (err) return _callback(err);
+
+ if (self._last_time === stats.mtime) return _callback();
+ self._last_time = stats.mtime;
+
+ fs.readFile(self._path, 'utf8', function(err, buffer) {
+ if (err) return _callback(err);
+
+ self._users = utils.parse_htpasswd(buffer);
+
+ _callback();
+ });
+ });
+};
diff --git a/lib/plugins/htpasswd/utils.js b/lib/plugins/htpasswd/utils.js
index 425e7b085..5a5f30013 100644
--- a/lib/plugins/htpasswd/utils.js
+++ b/lib/plugins/htpasswd/utils.js
@@ -1,68 +1,70 @@
-var crypto = require('crypto')
-var crypt3 = require('./crypt3')
-var md5 = require('apache-md5')
-var locker = require('../../file-locking')
+'use strict';
+
+let crypto = require('crypto');
+let crypt3 = require('./crypt3');
+let md5 = require('apache-md5');
+let locker = require('../../file-locking');
// this function neither unlocks file nor closes it
// it'll have to be done manually later
function lock_and_read(name, cb) {
- locker.readFile(name, {lock: true}, function (err, res) {
+ locker.readFile(name, {lock: true}, function(err, res) {
if (err) {
- return cb(err)
+ return cb(err);
}
- return cb(null, res)
- })
+ return cb(null, res);
+ });
}
// close and unlock file
function unlock_file(name, cb) {
- locker.unlockFile(name, cb)
+ locker.unlockFile(name, cb);
}
function parse_htpasswd(input) {
- var result = {}
+ let result = {};
input.split('\n').forEach(function(line) {
- var args = line.split(':', 3)
- if (args.length > 1) result[args[0]] = args[1]
- })
- return result
+ let args = line.split(':', 3);
+ if (args.length > 1) result[args[0]] = args[1];
+ });
+ return result;
}
function verify_password(user, passwd, hash) {
if (hash.indexOf('{PLAIN}') === 0) {
- return passwd === hash.substr(7)
+ return passwd === hash.substr(7);
} else if (hash.indexOf('{SHA}') === 0) {
- return crypto.createHash('sha1').update(passwd, 'binary').digest('base64') === hash.substr(5)
+ return crypto.createHash('sha1').update(passwd, 'binary').digest('base64') === hash.substr(5);
} else {
return (
// for backwards compatibility, first check md5 then check crypt3
md5(passwd, hash) === hash ||
crypt3(passwd, hash) === hash
- )
+ );
}
}
function add_user_to_htpasswd(body, user, passwd) {
if (user !== encodeURIComponent(user)) {
- var err = Error('username should not contain non-uri-safe characters')
- err.status = 409
- throw err
+ let err = Error('username should not contain non-uri-safe characters');
+ err.status = 409;
+ throw err;
}
if (crypt3) {
- passwd = crypt3(passwd)
+ passwd = crypt3(passwd);
} else {
- passwd = '{SHA}' + crypto.createHash('sha1').update(passwd, 'binary').digest('base64')
+ passwd = '{SHA}' + crypto.createHash('sha1').update(passwd, 'binary').digest('base64');
}
- var comment = 'autocreated ' + (new Date()).toJSON()
+ let comment = 'autocreated ' + (new Date()).toJSON();
- var newline = user + ':' + passwd + ':' + comment + '\n'
- if (body.length && body[body.length-1] !== '\n') newline = '\n' + newline
- return body + newline
+ let newline = user + ':' + passwd + ':' + comment + '\n';
+ if (body.length && body[body.length-1] !== '\n') newline = '\n' + newline;
+ return body + newline;
}
-module.exports.parse_htpasswd = parse_htpasswd
-module.exports.verify_password = verify_password
-module.exports.add_user_to_htpasswd = add_user_to_htpasswd
-module.exports.lock_and_read = lock_and_read
-module.exports.unlock_file = unlock_file
+module.exports.parse_htpasswd = parse_htpasswd;
+module.exports.verify_password = verify_password;
+module.exports.add_user_to_htpasswd = add_user_to_htpasswd;
+module.exports.lock_and_read = lock_and_read;
+module.exports.unlock_file = unlock_file;
diff --git a/lib/search.js b/lib/search.js
index 6bed026da..eda8fcfb8 100644
--- a/lib/search.js
+++ b/lib/search.js
@@ -1,49 +1,52 @@
-var lunr = require('lunr')
+'use strict';
-function Search() {
- var self = Object.create(Search.prototype)
- self.index = lunr(function() {
- this.field('name' , { boost: 10 })
- this.field('description' , { boost: 4 })
- this.field('author' , { boost: 6 })
- this.field('readme')
- })
- return self
+const lunr = require('lunr');
+
+class Search {
+ constructor() {
+ this.index = lunr(function() {
+ this.field('name', {boost: 10});
+ this.field('description', {boost: 4});
+ this.field('author', {boost: 6});
+ this.field('readme');
+ });
+ }
+
+ query(q) {
+ return q === '*'
+ ? this.storage.config.localList.get().map( function( pkg ) {
+ return {ref: pkg, score: 1};
+ }) : this.index.search(q);
+ }
+
+ add(pkg) {
+ this.index.add({
+ id: pkg.name,
+ name: pkg.name,
+ description: pkg.description,
+ author: pkg._npmUser ? pkg._npmUser.name : '???',
+ });
+ }
+
+ remove(name) {
+ this.index.remove({id: name});
+ }
+
+ reindex() {
+ let self = this;
+ this.storage.get_local(function(err, packages) {
+ if (err) throw err; // that function shouldn't produce any
+ let i = packages.length;
+ while (i--) {
+ self.add(packages[i]);
+ }
+ });
+ }
+
+ configureStorage(storage) {
+ this.storage = storage;
+ this.reindex();
+ }
}
-Search.prototype.query = function(q) {
- return q === '*'
- ? this.storage.config.localList.get().map( function( package ){ return { ref: package, score: 1 }; } )
- : this.index.search(q);
-}
-
-Search.prototype.add = function(package) {
- this.index.add({
- id: package.name,
- name: package.name,
- description: package.description,
- author: package._npmUser ? package._npmUser.name : '???',
- })
-},
-
-Search.prototype.remove = function(name) {
- this.index.remove({ id: name })
-}
-
-Search.prototype.reindex = function() {
- var self = this
- this.storage.get_local(function(err, packages) {
- if (err) throw err // that function shouldn't produce any
- var i = packages.length
- while (i--) {
- self.add(packages[i])
- }
- })
-}
-
-Search.prototype.configureStorage = function(storage) {
- this.storage = storage
- this.reindex()
-}
-
-module.exports = Search()
+module.exports = new Search();
diff --git a/lib/status-cats.js b/lib/status-cats.js
index 5c0016a86..f1cb4dd7d 100644
--- a/lib/status-cats.js
+++ b/lib/status-cats.js
@@ -1,7 +1,8 @@
+'use strict';
// see https://secure.flickr.com/photos/girliemac/sets/72157628409467125
-var images = {
+const images = {
100: 'aVvDhR', // '6512768893', // 100 - Continue
101: 'aXXExP', // '6540479029', // 101 - Switching Protocols
200: 'aVuVsF', // '6512628175', // 200 - OK
@@ -51,24 +52,24 @@ var images = {
508: 'aVdnYa', // '6509400445', // 508 - Loop Detected
509: 'aXXg1V', // '6540399865', // 509 - Bandwidth Limit Exceeded
599: 'aVdo7v', // '6509400929', // 599 - Network connect timeout error
-}
+};
module.exports.get_image = function(status) {
if (status in images) {
- return 'http://flic.kr/p/' + images[status]
- //return 'https://secure.flickr.com/photos/girliemac/'+images[status]+'/in/set-72157628409467125/lightbox/'
+ return 'http://flic.kr/p/' + images[status];
+ // return 'https://secure.flickr.com/photos/girliemac/'+images[status]+'/in/set-72157628409467125/lightbox/'
}
-}
+};
module.exports.middleware = function(req, res, next) {
- var _writeHead = res.writeHead
+ let _writeHead = res.writeHead;
res.writeHead = function(status) {
if (status in images) {
- res.setHeader('X-Status-Cat', module.exports.get_image(status))
+ res.setHeader('X-Status-Cat', module.exports.get_image(status));
}
- _writeHead.apply(res, arguments)
- }
+ _writeHead.apply(res, arguments);
+ };
- next()
-}
+ next();
+};
diff --git a/lib/storage.js b/lib/storage.js
index 823bd5281..abafdb471 100644
--- a/lib/storage.js
+++ b/lib/storage.js
@@ -1,521 +1,556 @@
-var assert = require('assert')
-var async = require('async')
-var Error = require('http-errors')
-var Stream = require('stream')
-var Local = require('./local-storage')
-var Logger = require('./logger')
-var MyStreams = require('./streams')
-var Proxy = require('./up-storage')
-var Utils = require('./utils')
+'use strict';
-module.exports = Storage
+const assert = require('assert');
+const async = require('async');
+const Error = require('http-errors');
+const Stream = require('stream');
+const Local = require('./local-storage');
+const Logger = require('./logger');
+const MyStreams = require('./streams');
+const Proxy = require('./up-storage');
+const Utils = require('./utils');
//
// Implements Storage interface
// (same for storage.js, local-storage.js, up-storage.js)
//
-function Storage(config) {
- var self = Object.create(Storage.prototype)
- self.config = config
+class Storage {
- // we support a number of uplinks, but only one local storage
- // Proxy and Local classes should have similar API interfaces
- self.uplinks = {}
- for (var p in config.uplinks) {
- self.uplinks[p] = Proxy(config.uplinks[p], config)
- self.uplinks[p].upname = p
- }
- self.local = Local(config)
- self.logger = Logger.logger.child()
-
- return self
-}
-
-//
-// Add a {name} package to a system
-//
-// Function checks if package with the same name is available from uplinks.
-// If it isn't, we create package locally
-//
-// Used storages: local (write) && uplinks
-//
-Storage.prototype.add_package = function(name, metadata, callback) {
- var self = this
-
- // NOTE:
- // - when we checking package for existance, we ask ALL uplinks
- // - when we publishing package, we only publish it to some of them
- // so all requests are necessary
-
- check_package_local(function(err) {
- if (err) return callback(err)
-
- check_package_remote(function(err) {
- if (err) return callback(err)
-
- publish_package(function(err) {
- if (err) return callback(err)
- callback()
- })
- })
- })
-
- function check_package_local(cb) {
- self.local.get_package(name, {}, function(err, results) {
- if (err && err.status !== 404) return cb(err)
-
- if (results) return cb( Error[409]('this package is already present') )
-
- cb()
- })
+ /**
+ *
+ * @param {*} config
+ */
+ constructor(config) {
+ this.config = config;
+ // we support a number of uplinks, but only one local storage
+ // Proxy and Local classes should have similar API interfaces
+ this.uplinks = {};
+ for (let p in config.uplinks) {
+ // instance for each up-link definition
+ this.uplinks[p] = new Proxy(config.uplinks[p], config);
+ this.uplinks[p].upname = p;
+ }
+ // an instance for local storage
+ this.local = new Local(config);
+ this.logger = Logger.logger.child();
}
- function check_package_remote(cb) {
- self._sync_package_with_uplinks(name, null, {}, function(err, results, err_results) {
- // something weird
- if (err && err.status !== 404) return cb(err)
+ /**
+ * Add a {name} package to a system
+ Function checks if package with the same name is available from uplinks.
+ If it isn't, we create package locally
+ Used storages: local (write) && uplinks
+ * @param {*} name
+ * @param {*} metadata
+ * @param {*} callback
+ */
+ add_package(name, metadata, callback) {
+ let self = this;
- // checking package
- if (results) return cb( Error[409]('this package is already present') )
+ // NOTE:
+ // - when we checking package for existance, we ask ALL uplinks
+ // - when we publishing package, we only publish it to some of them
+ // so all requests are necessary
- for (var i=0; i= 500)) {
- // report internal errors right away
- return callback(err)
- }
+ /**
+ * Remove a package from a system
+ Function removes a package from local storage
+ Used storages: local (write)
+ * @param {*} name
+ * @param {*} callback
+ */
+ remove_package(name, callback) {
+ return this.local.remove_package(name, callback);
+ }
- self._sync_package_with_uplinks(name, data, options, function(err, result, uplink_errors) {
- if (err) return callback(err)
- var whitelist = [ '_rev', 'name', 'versions', 'dist-tags', 'readme' ]
- for (var i in result) {
- if (whitelist.indexOf(i) === -1) delete result[i]
+ /**
+ Remove a tarball from a system
+ Function removes a tarball from local storage.
+ Tarball in question should not be linked to in any existing
+ versions, i.e. package version should be unpublished first.
+ Used storages: local (write)
+ * @param {*} name
+ * @param {*} filename
+ * @param {*} revision
+ * @param {*} callback
+ */
+ remove_tarball(name, filename, revision, callback) {
+ return this.local.remove_tarball(name, filename, revision, callback);
+ }
+
+ /**
+ * Upload a tarball for {name} package
+ Function is syncronous and returns a WritableStream
+ Used storages: local (write)
+ * @param {*} name
+ * @param {*} filename
+ */
+ add_tarball(name, filename) {
+ return this.local.add_tarball(name, filename);
+ }
+
+ /**
+ Get a tarball from a storage for {name} package
+ Function is syncronous and returns a ReadableStream
+ Function tries to read tarball locally, if it fails then it reads package
+ information in order to figure out where we can get this tarball from
+ Used storages: local || uplink (just one)
+ * @param {*} name
+ * @param {*} filename
+ */
+ get_tarball(name, filename) {
+ let stream = MyStreams.ReadTarballStream();
+ stream.abort = function() {};
+
+ let self = this;
+
+ // if someone requesting tarball, it means that we should already have some
+ // information about it, so fetching package info is unnecessary
+
+ // trying local first
+ let rstream = self.local.get_tarball(name, filename);
+ let is_open = false;
+ rstream.on('error', function(err) {
+ if (is_open || err.status !== 404) {
+ return stream.emit('error', err);
}
- Utils.normalize_dist_tags(result)
+ // local reported 404
+ let err404 = err;
+ rstream.abort();
+ rstream = null; // gc
- // npm can throw if this field doesn't exist
- result._attachments = {}
-
- callback(null, result, uplink_errors)
- })
- })
-}
-
-//
-// Retrieve remote and local packages more recent than {startkey}
-//
-// Function streams all packages from all uplinks first, and then
-// local packages.
-//
-// Note that local packages could override registry ones just because
-// they appear in JSON last. That's a trade-off we make to avoid
-// memory issues.
-//
-// Used storages: local && uplink (proxy_access)
-//
-Storage.prototype.search = function(startkey, options) {
- var self = this
-
- var stream = new Stream.PassThrough({ objectMode: true })
-
- async.eachSeries(Object.keys(self.uplinks), function(up_name, cb) {
- // shortcut: if `local=1` is supplied, don't call uplinks
- if (options.req.query.local !== undefined) return cb()
-
- var lstream = self.uplinks[up_name].search(startkey, options)
- lstream.pipe(stream, { end: false })
- lstream.on('error', function (err) {
- self.logger.error({ err: err }, 'uplink error: @{err.message}')
- cb(), cb = function () {}
- })
- lstream.on('end', function () {
- cb(), cb = function () {}
- })
-
- stream.abort = function () {
- if (lstream.abort) lstream.abort()
- cb(), cb = function () {}
- }
- }, function () {
- var lstream = self.local.search(startkey, options)
- stream.abort = function () { lstream.abort() }
- lstream.pipe(stream, { end: true })
- lstream.on('error', function (err) {
- self.logger.error({ err: err }, 'search error: @{err.message}')
- stream.end()
- })
- })
-
- return stream
-}
-
-Storage.prototype.get_local = function(callback) {
- var self = this
- var locals = this.config.localList.get()
- var packages = []
-
- var getPackage = function(i) {
- self.local.get_package(locals[i], function(err, info) {
- if (!err) {
- var latest = info['dist-tags'].latest
- if (latest && info.versions[latest]) {
- packages.push(info.versions[latest])
+ self.local.get_package(name, function(err, info) {
+ if (!err && info._distfiles && info._distfiles[filename] != null) {
+ // information about this file exists locally
+ serve_file(info._distfiles[filename]);
} else {
- self.logger.warn( { package: locals[i] }
- , 'package @{package} does not have a "latest" tag?' )
+ // we know nothing about this file, trying to get information elsewhere
+
+ self._sync_package_with_uplinks(name, info, {}, function(err, info) {
+ if (err) return stream.emit('error', err);
+
+ if (!info._distfiles || info._distfiles[filename] == null) {
+ return stream.emit('error', err404);
+ }
+
+ serve_file(info._distfiles[filename]);
+ });
+ }
+ });
+ });
+ rstream.on('content-length', function(v) {
+ stream.emit('content-length', v);
+ });
+ rstream.on('open', function() {
+ is_open = true;
+ rstream.pipe(stream);
+ });
+ return stream;
+
+ function serve_file(file) {
+ let uplink = null;
+ for (let p in self.uplinks) {
+ if (self.uplinks[p].can_fetch_url(file.url)) {
+ uplink = self.uplinks[p];
}
}
-
- if (i >= locals.length - 1) {
- callback(null, packages)
- } else {
- getPackage(i + 1)
+ if (uplink == null) {
+ uplink = Proxy({
+ url: file.url,
+ _autogenerated: true,
+ }, self.config);
}
- })
+
+ let savestream = self.local.add_tarball(name, filename);
+ var on_open = function() {
+ on_open = function() {}; // prevent it from being called twice
+ let rstream2 = uplink.get_url(file.url);
+ rstream2.on('error', function(err) {
+ if (savestream) savestream.abort();
+ savestream = null;
+ stream.emit('error', err);
+ });
+ rstream2.on('end', function() {
+ if (savestream) savestream.done();
+ });
+
+ rstream2.on('content-length', function(v) {
+ stream.emit('content-length', v);
+ if (savestream) savestream.emit('content-length', v);
+ });
+ rstream2.pipe(stream);
+ if (savestream) rstream2.pipe(savestream);
+ };
+
+ savestream.on('open', function() {
+ on_open();
+ });
+ savestream.on('error', function(err) {
+ self.logger.warn( {err: err}
+ , 'error saving file: @{err.message}\n@{err.stack}' );
+ if (savestream) savestream.abort();
+ savestream = null;
+ on_open();
+ });
+ }
}
- if (locals.length) {
- getPackage(0)
- } else {
- callback(null, [])
+ /**
+ Retrieve a package metadata for {name} package
+ Function invokes local.get_package and uplink.get_package for every
+ uplink with proxy_access rights against {name} and combines results
+ into one json object
+ Used storages: local && uplink (proxy_access)
+ * @param {*} name
+ * @param {*} options
+ * @param {*} callback
+ */
+ get_package(name, options, callback) {
+ if (typeof(options) === 'function') {
+ callback = options, options = {};
+ }
+
+ this.local.get_package(name, options, (err, data) => {
+ if (err && (!err.status || err.status >= 500)) {
+ // report internal errors right away
+ return callback(err);
+ }
+
+ this._sync_package_with_uplinks(name, data, options, function(err, result, uplink_errors) {
+ if (err) return callback(err);
+ const whitelist = ['_rev', 'name', 'versions', 'dist-tags', 'readme'];
+ for (let i in result) {
+ if (whitelist.indexOf(i) === -1) delete result[i];
+ }
+
+ Utils.normalize_dist_tags(result);
+
+ // npm can throw if this field doesn't exist
+ result._attachments = {};
+
+ callback(null, result, uplink_errors);
+ });
+ });
}
+
+ /**
+ Retrieve remote and local packages more recent than {startkey}
+ Function streams all packages from all uplinks first, and then
+ local packages.
+ Note that local packages could override registry ones just because
+ they appear in JSON last. That's a trade-off we make to avoid
+ memory issues.
+ Used storages: local && uplink (proxy_access)
+ * @param {*} startkey
+ * @param {*} options
+ */
+ search(startkey, options) {
+ let self = this;
+
+ let stream = new Stream.PassThrough({objectMode: true});
+
+ async.eachSeries(Object.keys(this.uplinks), function(up_name, cb) {
+ // shortcut: if `local=1` is supplied, don't call uplinks
+ if (options.req.query.local !== undefined) return cb();
+
+ let lstream = self.uplinks[up_name].search(startkey, options);
+ lstream.pipe(stream, {end: false});
+ lstream.on('error', function(err) {
+ self.logger.error({err: err}, 'uplink error: @{err.message}');
+ cb(), cb = function() {};
+ });
+ lstream.on('end', function() {
+ cb(), cb = function() {};
+ });
+
+ stream.abort = function() {
+ if (lstream.abort) lstream.abort();
+ cb(), cb = function() {};
+ };
+ }, function() {
+ let lstream = self.local.search(startkey, options);
+ stream.abort = function() {
+ lstream.abort();
+};
+ lstream.pipe(stream, {end: true});
+ lstream.on('error', function(err) {
+ self.logger.error({err: err}, 'search error: @{err.message}');
+ stream.end();
+ });
+ });
+
+ return stream;
+ }
+
+ /**
+ *
+ * @param {*} callback
+ */
+ get_local(callback) {
+ let self = this;
+ let locals = this.config.localList.get();
+ let packages = [];
+
+ var getPackage = function(i) {
+ self.local.get_package(locals[i], function(err, info) {
+ if (!err) {
+ let latest = info['dist-tags'].latest;
+ if (latest && info.versions[latest]) {
+ packages.push(info.versions[latest]);
+ } else {
+ self.logger.warn( {package: locals[i]}
+ , 'package @{package} does not have a "latest" tag?' );
+ }
+ }
+
+ if (i >= locals.length - 1) {
+ callback(null, packages);
+ } else {
+ getPackage(i + 1);
+ }
+ });
+ };
+
+ if (locals.length) {
+ getPackage(0);
+ } else {
+ callback(null, []);
+ }
+ }
+
+ /**
+ * Function fetches package information from uplinks and synchronizes it with local data
+ if package is available locally, it MUST be provided in pkginfo
+ returns callback(err, result, uplink_errors)
+ * @param {*} name
+ * @param {*} pkginfo
+ * @param {*} options
+ * @param {*} callback
+ */
+ _sync_package_with_uplinks(name, pkginfo, options, callback) {
+ let self = this;
+ let exists = false;
+ if (!pkginfo) {
+ exists = false;
+
+ pkginfo = {
+ 'name': name,
+ 'versions': {},
+ 'dist-tags': {},
+ '_uplinks': {},
+ };
+ } else {
+ exists = true;
+ }
+
+ let uplinks = [];
+ for (let i in self.uplinks) {
+ if (self.config.can_proxy_to(name, i)) {
+ uplinks.push(self.uplinks[i]);
+ }
+ }
+
+ async.map(uplinks, function(up, cb) {
+ let _options = Object.assign({}, options);
+ if (Utils.is_object(pkginfo._uplinks[up.upname])) {
+ let fetched = pkginfo._uplinks[up.upname].fetched;
+ if (fetched && fetched > (Date.now() - up.maxage)) {
+ return cb();
+ }
+
+ _options.etag = pkginfo._uplinks[up.upname].etag;
+ }
+
+ up.get_package(name, _options, function(err, up_res, etag) {
+ if (err && err.status === 304)
+ pkginfo._uplinks[up.upname].fetched = Date.now();
+
+ if (err || !up_res) return cb(null, [err || Error('no data')]);
+
+ try {
+ Utils.validate_metadata(up_res, name);
+ } catch(err) {
+ self.logger.error({
+ sub: 'out',
+ err: err,
+ }, 'package.json validating error @{!err.message}\n@{err.stack}');
+ return cb(null, [err]);
+ }
+
+ pkginfo._uplinks[up.upname] = {
+ etag: etag,
+ fetched: Date.now(),
+ };
+ for (let i in up_res.versions) {
+ // this won't be serialized to json,
+ // kinda like an ES6 Symbol
+ // FIXME: perhaps Symbol('_verdaccio_uplink') here?
+ Object.defineProperty(up_res.versions[i], '_verdaccio_uplink', {
+ value: up.upname,
+ enumerable: false,
+ configurable: false,
+ writable: true,
+ });
+ }
+
+ try {
+ Storage._merge_versions(pkginfo, up_res, self.config);
+ } catch(err) {
+ self.logger.error({
+ sub: 'out',
+ err: err,
+ }, 'package.json parsing error @{!err.message}\n@{err.stack}');
+ return cb(null, [err]);
+ }
+
+ // if we got to this point, assume that the correct package exists
+ // on the uplink
+ exists = true;
+ cb();
+ });
+ }, function(err, uplink_errors) {
+ assert(!err && Array.isArray(uplink_errors));
+
+ if (!exists) {
+ return callback( Error[404]('no such package available')
+ , null
+ , uplink_errors );
+ }
+
+ self.local.update_versions(name, pkginfo, function(err, pkginfo) {
+ if (err) return callback(err);
+ return callback(null, pkginfo, uplink_errors);
+ });
+ });
+ }
+
+ /**
+ * Function gets a local info and an info from uplinks and tries to merge it
+ exported for unit tests only.
+ * @param {*} local
+ * @param {*} up
+ * @param {*} config
+ */
+ static _merge_versions(local, up, config) {
+ // copy new versions to a cache
+ // NOTE: if a certain version was updated, we can't refresh it reliably
+ for (var i in up.versions) {
+ if (local.versions[i] == null) {
+ local.versions[i] = up.versions[i];
+ }
+ }
+
+ // refresh dist-tags
+ for (var i in up['dist-tags']) {
+ if (local['dist-tags'][i] !== up['dist-tags'][i]) {
+ local['dist-tags'][i] = up['dist-tags'][i];
+ if (i === 'latest') {
+ // if remote has more fresh package, we should borrow its readme
+ local.readme = up.readme;
+ }
+ }
+ }
+ }
+
}
-// function fetches package information from uplinks and synchronizes it with local data
-// if package is available locally, it MUST be provided in pkginfo
-// returns callback(err, result, uplink_errors)
-Storage.prototype._sync_package_with_uplinks = function(name, pkginfo, options, callback) {
- var self = this
-
- if (!pkginfo) {
- var exists = false
-
- pkginfo = {
- name : name,
- versions : {},
- 'dist-tags' : {},
- _uplinks : {},
- }
- } else {
- var exists = true
- }
-
- var uplinks = []
- for (var i in self.uplinks) {
- if (self.config.can_proxy_to(name, i)) {
- uplinks.push(self.uplinks[i])
- }
- }
-
- async.map(uplinks, function(up, cb) {
- var _options = Object.assign({}, options)
- if (Utils.is_object(pkginfo._uplinks[up.upname])) {
- var fetched = pkginfo._uplinks[up.upname].fetched
- if (fetched && fetched > (Date.now() - up.maxage)) {
- return cb()
- }
-
- _options.etag = pkginfo._uplinks[up.upname].etag
- }
-
- up.get_package(name, _options, function(err, up_res, etag) {
- if (err && err.status === 304)
- pkginfo._uplinks[up.upname].fetched = Date.now()
-
- if (err || !up_res) return cb(null, [err || Error('no data')])
-
- try {
- Utils.validate_metadata(up_res, name)
- } catch(err) {
- self.logger.error({
- sub: 'out',
- err: err,
- }, 'package.json validating error @{!err.message}\n@{err.stack}')
- return cb(null, [ err ])
- }
-
- pkginfo._uplinks[up.upname] = {
- etag: etag,
- fetched: Date.now()
- }
-
- for (var i in up_res.versions) {
- // this won't be serialized to json,
- // kinda like an ES6 Symbol
- Object.defineProperty(up_res.versions[i], '_verdaccio_uplink', {
- value : up.upname,
- enumerable : false,
- configurable : false,
- writable : true,
- })
- }
-
- try {
- Storage._merge_versions(pkginfo, up_res, self.config)
- } catch(err) {
- self.logger.error({
- sub: 'out',
- err: err,
- }, 'package.json parsing error @{!err.message}\n@{err.stack}')
- return cb(null, [ err ])
- }
-
- // if we got to this point, assume that the correct package exists
- // on the uplink
- exists = true
- cb()
- })
- }, function(err, uplink_errors) {
- assert(!err && Array.isArray(uplink_errors))
-
- if (!exists) {
- return callback( Error[404]('no such package available')
- , null
- , uplink_errors )
- }
-
- self.local.update_versions(name, pkginfo, function(err, pkginfo) {
- if (err) return callback(err)
- return callback(null, pkginfo, uplink_errors)
- })
- })
-}
-
-// function gets a local info and an info from uplinks and tries to merge it
-// exported for unit tests only
-Storage._merge_versions = function(local, up, config) {
- // copy new versions to a cache
- // NOTE: if a certain version was updated, we can't refresh it reliably
- for (var i in up.versions) {
- if (local.versions[i] == null) {
- local.versions[i] = up.versions[i]
- }
- }
-
- // refresh dist-tags
- for (var i in up['dist-tags']) {
- if (local['dist-tags'][i] !== up['dist-tags'][i]) {
- local['dist-tags'][i] = up['dist-tags'][i]
- if (i === 'latest') {
- // if remote has more fresh package, we should borrow its readme
- local.readme = up.readme
- }
- }
- }
-}
+module.exports = Storage;
diff --git a/lib/streams.js b/lib/streams.js
index 43a1e4a02..9a105aa17 100644
--- a/lib/streams.js
+++ b/lib/streams.js
@@ -1,60 +1,62 @@
-var Stream = require('stream')
-var Util = require('util')
+'use strict';
-module.exports.ReadTarballStream = ReadTarball
-module.exports.UploadTarballStream = UploadTarball
+let Stream = require('stream');
+let Util = require('util');
+
+module.exports.ReadTarballStream = ReadTarball;
+module.exports.UploadTarballStream = UploadTarball;
//
// This stream is used to read tarballs from repository
//
function ReadTarball(options) {
- var self = new Stream.PassThrough(options)
- Object.setPrototypeOf(self, ReadTarball.prototype)
+ let self = new Stream.PassThrough(options);
+ Object.setPrototypeOf(self, ReadTarball.prototype);
// called when data is not needed anymore
- add_abstract_method(self, 'abort')
+ add_abstract_method(self, 'abort');
- return self
+ return self;
}
-Util.inherits(ReadTarball, Stream.PassThrough)
+Util.inherits(ReadTarball, Stream.PassThrough);
//
// This stream is used to upload tarballs to a repository
//
function UploadTarball(options) {
- var self = new Stream.PassThrough(options)
- Object.setPrototypeOf(self, UploadTarball.prototype)
+ let self = new Stream.PassThrough(options);
+ Object.setPrototypeOf(self, UploadTarball.prototype);
// called when user closes connection before upload finishes
- add_abstract_method(self, 'abort')
+ add_abstract_method(self, 'abort');
// called when upload finishes successfully
- add_abstract_method(self, 'done')
+ add_abstract_method(self, 'done');
- return self
+ return self;
}
-Util.inherits(UploadTarball, Stream.PassThrough)
+Util.inherits(UploadTarball, Stream.PassThrough);
//
// This function intercepts abstract calls and replays them allowing
// us to attach those functions after we are ready to do so
//
function add_abstract_method(self, name) {
- self._called_methods = self._called_methods || {}
+ self._called_methods = self._called_methods || {};
self.__defineGetter__(name, function() {
return function() {
- self._called_methods[name] = true
- }
- })
+ self._called_methods[name] = true;
+ };
+ });
self.__defineSetter__(name, function(fn) {
- delete self[name]
- self[name] = fn
+ delete self[name];
+ self[name] = fn;
if (self._called_methods && self._called_methods[name]) {
- delete self._called_methods[name]
- self[name]()
+ delete self._called_methods[name];
+ self[name]();
}
- })
+ });
}
diff --git a/lib/up-storage.js b/lib/up-storage.js
index 5792d396d..b8b19c474 100644
--- a/lib/up-storage.js
+++ b/lib/up-storage.js
@@ -1,374 +1,385 @@
-var JSONStream = require('JSONStream')
-var Error = require('http-errors')
-var request = require('request')
-var Stream = require('readable-stream')
-var URL = require('url')
-var parse_interval = require('./config').parse_interval
-var Logger = require('./logger')
-var MyStreams = require('./streams')
-var Utils = require('./utils')
-var encode = function(thing) {
+'use strict';
+
+const JSONStream = require('JSONStream');
+const Error = require('http-errors');
+const request = require('request');
+const Stream = require('readable-stream');
+const URL = require('url');
+const parse_interval = require('./config').parse_interval;
+const Logger = require('./logger');
+const MyStreams = require('./streams');
+const Utils = require('./utils');
+const encode = function(thing) {
return encodeURIComponent(thing).replace(/^%40/, '@');
};
-module.exports = Storage
-
-//
-// Implements Storage interface
-// (same for storage.js, local-storage.js, up-storage.js)
-//
-function Storage(config, mainconfig) {
- var self = Object.create(Storage.prototype)
- self.config = config
- self.failed_requests = 0
- self.userAgent = mainconfig.user_agent
- self.ca = config.ca
- self.logger = Logger.logger.child({sub: 'out'})
- self.server_id = mainconfig.server_id
-
- self.url = URL.parse(self.config.url)
-
- _setupProxy.call(self, self.url.hostname, config, mainconfig, self.url.protocol === 'https:')
-
- self.config.url = self.config.url.replace(/\/$/, '')
- if (Number(self.config.timeout) >= 1000) {
- self.logger.warn([ 'Too big timeout value: ' + self.config.timeout,
- 'We changed time format to nginx-like one',
- '(see http://wiki.nginx.org/ConfigNotation)',
- 'so please update your config accordingly' ].join('\n'))
- }
-
- // a bunch of different configurable timers
- self.maxage = parse_interval(config_get('maxage' , '2m' ))
- self.timeout = parse_interval(config_get('timeout' , '30s'))
- self.max_fails = Number(config_get('max_fails' , 2 ))
- self.fail_timeout = parse_interval(config_get('fail_timeout', '5m' ))
- return self
-
- // just a helper (`config[key] || default` doesn't work because of zeroes)
- function config_get(key, def) {
- return config[key] != null ? config[key] : def
- }
-}
-
-function _setupProxy(hostname, config, mainconfig, isHTTPS) {
- var no_proxy
- var proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy'
+const _setupProxy = function(hostname, config, mainconfig, isHTTPS) {
+ let no_proxy;
+ let proxy_key = isHTTPS ? 'https_proxy' : 'http_proxy';
// get http_proxy and no_proxy configs
if (proxy_key in config) {
- this.proxy = config[proxy_key]
+ this.proxy = config[proxy_key];
} else if (proxy_key in mainconfig) {
- this.proxy = mainconfig[proxy_key]
+ this.proxy = mainconfig[proxy_key];
}
if ('no_proxy' in config) {
- no_proxy = config.no_proxy
+ no_proxy = config.no_proxy;
} else if ('no_proxy' in mainconfig) {
- no_proxy = mainconfig.no_proxy
+ no_proxy = mainconfig.no_proxy;
}
// use wget-like algorithm to determine if proxy shouldn't be used
- if (hostname[0] !== '.') hostname = '.' + hostname
+ if (hostname[0] !== '.') {
+ hostname = '.' + hostname;
+ }
if (typeof(no_proxy) === 'string' && no_proxy.length) {
- no_proxy = no_proxy.split(',')
+ no_proxy = no_proxy.split(',');
}
if (Array.isArray(no_proxy)) {
- for (var i=0; i= 1000) {
+ this.logger.warn(['Too big timeout value: ' + this.config.timeout,
+ 'We changed time format to nginx-like one',
+ '(see http://wiki.nginx.org/ConfigNotation)',
+ 'so please update your config accordingly'].join('\n'));
+ }
+
+ // a bunch of different configurable timers
+ this.maxage = parse_interval(config_get('maxage', '2m' ));
+ this.timeout = parse_interval(config_get('timeout', '30s'));
+ this.max_fails = Number(config_get('max_fails', 2 ));
+ this.fail_timeout = parse_interval(config_get('fail_timeout', '5m' ));
+ return this;
+
+ // just a helper (`config[key] || default` doesn't work because of zeroes)
+ function config_get(key, def) {
+ return config[key] != null ? config[key] : def;
+ }
}
}
+
Storage.prototype.request = function(options, cb) {
if (!this.status_check()) {
- var req = new Stream.Readable()
+ var req = new Stream.Readable();
process.nextTick(function() {
- if (typeof(cb) === 'function') cb(Error('uplink is offline'))
- req.emit('error', Error('uplink is offline'))
- })
- req._read = function(){}
+ if (typeof(cb) === 'function') cb(Error('uplink is offline'));
+ req.emit('error', Error('uplink is offline'));
+ });
+ req._read = function() {};
// preventing 'Uncaught, unspecified "error" event'
- req.on('error', function(){})
- return req
+ req.on('error', function() {});
+ return req;
}
- var self = this
- var headers = options.headers || {}
- headers['Accept'] = headers['Accept'] || 'application/json'
- headers['Accept-Encoding'] = headers['Accept-Encoding'] || 'gzip'
+ let self = this;
+ let headers = options.headers || {};
+ headers['Accept'] = headers['Accept'] || 'application/json';
+ headers['Accept-Encoding'] = headers['Accept-Encoding'] || 'gzip';
// registry.npmjs.org will only return search result if user-agent include string 'npm'
- headers['User-Agent'] = headers['User-Agent'] || `npm (${this.userAgent})`
- this._add_proxy_headers(options.req, headers)
+ headers['User-Agent'] = headers['User-Agent'] || `npm (${this.userAgent})`;
+ this._add_proxy_headers(options.req, headers);
// add/override headers specified in the config
- for (var key in this.config.headers) {
- headers[key] = this.config.headers[key]
+ for (let key in this.config.headers) {
+ headers[key] = this.config.headers[key];
}
- var method = options.method || 'GET'
- var uri = options.uri_full || (this.config.url + options.uri)
+ let method = options.method || 'GET';
+ let uri = options.uri_full || (this.config.url + options.uri);
self.logger.info({
- method : method,
- headers : headers,
- uri : uri,
- }, "making request: '@{method} @{uri}'")
+ method: method,
+ headers: headers,
+ uri: uri,
+ }, 'making request: \'@{method} @{uri}\'');
if (Utils.is_object(options.json)) {
- var json = JSON.stringify(options.json)
- headers['Content-Type'] = headers['Content-Type'] || 'application/json'
+ var json = JSON.stringify(options.json);
+ headers['Content-Type'] = headers['Content-Type'] || 'application/json';
}
- var request_callback = cb ? (function (err, res, body) {
- var error
- var res_length = err ? 0 : body.length
+ let request_callback = cb ? (function(err, res, body) {
+ let error;
+ let res_length = err ? 0 : body.length;
- do_decode()
- do_log()
- cb(err, res, body)
+ do_decode();
+ do_log();
+ cb(err, res, body);
function do_decode() {
if (err) {
- error = err.message
- return
+ error = err.message;
+ return;
}
if (options.json && res.statusCode < 300) {
try {
- body = JSON.parse(body.toString('utf8'))
+ body = JSON.parse(body.toString('utf8'));
} catch(_err) {
- body = {}
- err = _err
- error = err.message
+ body = {};
+ err = _err;
+ error = err.message;
}
}
if (!err && Utils.is_object(body)) {
if (typeof(body.error) === 'string') {
- error = body.error
+ error = body.error;
}
}
}
function do_log() {
- var message = '@{!status}, req: \'@{request.method} @{request.url}\''
+ let message = '@{!status}, req: \'@{request.method} @{request.url}\'';
message += error
? ', error: @{!error}'
- : ', bytes: @{bytes.in}/@{bytes.out}'
+ : ', bytes: @{bytes.in}/@{bytes.out}';
self.logger.warn({
- err : err,
- request : { method: method, url: uri },
- level : 35, // http
- status : res != null ? res.statusCode : 'ERR',
- error : error,
- bytes : {
- in : json ? json.length : 0,
- out : res_length || 0,
- }
- }, message)
+ err: err,
+ request: {method: method, url: uri},
+ level: 35, // http
+ status: res != null ? res.statusCode : 'ERR',
+ error: error,
+ bytes: {
+ in: json ? json.length : 0,
+ out: res_length || 0,
+ },
+ }, message);
}
- }) : undefined
+ }) : undefined;
var req = request({
- url : uri,
- method : method,
- headers : headers,
- body : json,
- ca : this.ca,
- proxy : this.proxy,
- encoding : null,
- gzip : true,
- timeout : this.timeout,
- }, request_callback)
+ url: uri,
+ method: method,
+ headers: headers,
+ body: json,
+ ca: this.ca,
+ proxy: this.proxy,
+ encoding: null,
+ gzip: true,
+ timeout: this.timeout,
+ }, request_callback);
- var status_called = false
+ let status_called = false;
req.on('response', function(res) {
if (!req._verdaccio_aborted && !status_called) {
- status_called = true
- self.status_check(true)
+ status_called = true;
+ self.status_check(true);
}
if (!request_callback) {
- ;(function do_log() {
- var message = '@{!status}, req: \'@{request.method} @{request.url}\' (streaming)'
+ (function do_log() {
+ let message = '@{!status}, req: \'@{request.method} @{request.url}\' (streaming)';
self.logger.warn({
- request : { method: method, url: uri },
- level : 35, // http
- status : res != null ? res.statusCode : 'ERR',
- }, message)
- })()
+ request: {method: method, url: uri},
+ level: 35, // http
+ status: res != null ? res.statusCode : 'ERR',
+ }, message);
+ })();
}
- })
+ });
req.on('error', function(_err) {
if (!req._verdaccio_aborted && !status_called) {
- status_called = true
- self.status_check(false)
+ status_called = true;
+ self.status_check(false);
}
- })
- return req
-}
+ });
+ return req;
+};
Storage.prototype.status_check = function(alive) {
if (arguments.length === 0) {
if (this.failed_requests >= this.max_fails
&& Math.abs(Date.now() - this.last_request_time) < this.fail_timeout) {
- return false
+ return false;
} else {
- return true
+ return true;
}
} else {
if (alive) {
if (this.failed_requests >= this.max_fails) {
- this.logger.warn({ host: this.url.host }, 'host @{host} is back online')
+ this.logger.warn({host: this.url.host}, 'host @{host} is back online');
}
- this.failed_requests = 0
+ this.failed_requests = 0;
} else {
- this.failed_requests++
+ this.failed_requests++;
if (this.failed_requests === this.max_fails) {
- this.logger.warn({ host: this.url.host }, 'host @{host} is now offline')
+ this.logger.warn({host: this.url.host}, 'host @{host} is now offline');
}
}
- this.last_request_time = Date.now()
+ this.last_request_time = Date.now();
}
-}
+};
Storage.prototype.can_fetch_url = function(url) {
- url = URL.parse(url)
+ url = URL.parse(url);
return url.protocol === this.url.protocol
&& url.host === this.url.host
- && url.path.indexOf(this.url.path) === 0
-}
+ && url.path.indexOf(this.url.path) === 0;
+};
Storage.prototype.get_package = function(name, options, callback) {
- if (typeof(options) === 'function') callback = options, options = {}
+ if (typeof(options) === 'function') callback = options, options = {};
- var headers = {}
+ let headers = {};
if (options.etag) {
- headers['If-None-Match'] = options.etag
- headers['Accept'] = 'application/octet-stream'
+ headers['If-None-Match'] = options.etag;
+ headers['Accept'] = 'application/octet-stream';
}
this.request({
- uri : '/' + encode(name),
- json : true,
- headers : headers,
- req : options.req,
+ uri: '/' + encode(name),
+ json: true,
+ headers: headers,
+ req: options.req,
}, function(err, res, body) {
- if (err) return callback(err)
+ if (err) return callback(err);
if (res.statusCode === 404) {
- return callback( Error[404]("package doesn't exist on uplink") )
+ return callback( Error[404]('package doesn\'t exist on uplink') );
}
if (!(res.statusCode >= 200 && res.statusCode < 300)) {
- var error = Error('bad status code: ' + res.statusCode)
- error.remoteStatus = res.statusCode
- return callback(error)
+ let error = Error('bad status code: ' + res.statusCode);
+ error.remoteStatus = res.statusCode;
+ return callback(error);
}
- callback(null, body, res.headers.etag)
- })
-}
+ callback(null, body, res.headers.etag);
+ });
+};
Storage.prototype.get_tarball = function(name, options, filename) {
- if (!options) options = {}
- return this.get_url(this.config.url + '/' + name + '/-/' + filename)
-}
+ if (!options) options = {};
+ return this.get_url(this.config.url + '/' + name + '/-/' + filename);
+};
Storage.prototype.get_url = function(url) {
- var stream = MyStreams.ReadTarballStream()
- stream.abort = function() {}
- var current_length = 0, expected_length
+ let stream = MyStreams.ReadTarballStream();
+ stream.abort = function() {};
+ let current_length = 0, expected_length;
- var rstream = this.request({
+ let rstream = this.request({
uri_full: url,
encoding: null,
- headers: { Accept: 'application/octet-stream' },
- })
+ headers: {Accept: 'application/octet-stream'},
+ });
rstream.on('response', function(res) {
if (res.statusCode === 404) {
- return stream.emit('error', Error[404]("file doesn't exist on uplink"))
+ return stream.emit('error', Error[404]('file doesn\'t exist on uplink'));
}
if (!(res.statusCode >= 200 && res.statusCode < 300)) {
- return stream.emit('error', Error('bad uplink status code: ' + res.statusCode))
+ return stream.emit('error', Error('bad uplink status code: ' + res.statusCode));
}
if (res.headers['content-length']) {
- expected_length = res.headers['content-length']
- stream.emit('content-length', res.headers['content-length'])
+ expected_length = res.headers['content-length'];
+ stream.emit('content-length', res.headers['content-length']);
}
- rstream.pipe(stream)
- })
+ rstream.pipe(stream);
+ });
rstream.on('error', function(err) {
- stream.emit('error', err)
- })
+ stream.emit('error', err);
+ });
rstream.on('data', function(d) {
- current_length += d.length
- })
+ current_length += d.length;
+ });
rstream.on('end', function(d) {
- if (d) current_length += d.length
+ if (d) current_length += d.length;
if (expected_length && current_length != expected_length)
- stream.emit('error', Error('content length mismatch'))
- })
- return stream
-}
+ stream.emit('error', Error('content length mismatch'));
+ });
+ return stream;
+};
Storage.prototype.search = function(startkey, options) {
- var self = this
+ let self = this;
- var stream = new Stream.PassThrough({ objectMode: true })
+ let stream = new Stream.PassThrough({objectMode: true});
- var req = self.request({
+ let req = self.request({
uri: options.req.url,
req: options.req,
headers: {
- referer: options.req.headers.referer
- }
- })
+ referer: options.req.headers.referer,
+ },
+ });
- req.on('response', function (res) {
+ req.on('response', (res) => {
if (!String(res.statusCode).match(/^2\d\d$/)) {
- return stream.emit('error', Error('bad status code ' + res.statusCode + ' from uplink'))
+ return stream.emit('error', Error('bad status code ' + res.statusCode + ' from uplink'));
}
- res.pipe(JSONStream.parse('*')).on('data', function (pkg) {
+ res.pipe(JSONStream.parse('*')).on('data', (pkg) => {
if (Utils.is_object(pkg)) {
- stream.emit('data', pkg)
+ stream.emit('data', pkg);
}
- })
- res.on('end', function () {
- stream.emit('end')
- })
- })
+ });
+ res.on('end', () => {
+ stream.emit('end');
+ });
+ });
- req.on('error', function (err) {
- stream.emit('error', err)
- })
+ req.on('error', (err) => {
+ stream.emit('error', err);
+ });
- stream.abort = function () {
- req.abort()
- stream.emit('end')
- }
+ stream.abort = () => {
+ req.abort();
+ stream.emit('end');
+ };
- return stream
-}
+
+ return stream;
+};
Storage.prototype._add_proxy_headers = function(req, headers) {
if (req) {
@@ -383,7 +394,7 @@ Storage.prototype._add_proxy_headers = function(req, headers) {
req && req.headers['x-forwarded-for']
? req.headers['x-forwarded-for'] + ', '
: ''
- ) + req.connection.remoteAddress
+ ) + req.connection.remoteAddress;
}
}
@@ -391,7 +402,10 @@ Storage.prototype._add_proxy_headers = function(req, headers) {
headers['Via'] =
req && req.headers['via']
? req.headers['via'] + ', '
- : ''
+ : '';
- headers['Via'] += '1.1 ' + this.server_id + ' (Verdaccio)'
-}
+ headers['Via'] += '1.1 ' + this.server_id + ' (Verdaccio)';
+};
+
+
+module.exports = Storage;
diff --git a/lib/utils.js b/lib/utils.js
index f342f5816..483287269 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -1,25 +1,27 @@
-var assert = require('assert')
-var Semver = require('semver')
-var URL = require('url')
-var Logger = require('./logger')
+'use strict';
+
+let assert = require('assert');
+let Semver = require('semver');
+let URL = require('url');
+let Logger = require('./logger');
module.exports.validate_package = function(name) {
- name = name.split('/', 2)
+ name = name.split('/', 2);
if (name.length === 1) {
// normal package
- return module.exports.validate_name(name[0])
+ return module.exports.validate_name(name[0]);
} else {
// scoped package
return name[0][0] === '@'
&& module.exports.validate_name(name[0].slice(1))
- && module.exports.validate_name(name[1])
+ && module.exports.validate_name(name[1]);
}
-}
+};
// from normalize-package-data/lib/fixer.js
module.exports.validate_name = function(name) {
- if (typeof(name) !== 'string') return false
- name = name.toLowerCase()
+ if (typeof(name) !== 'string') return false;
+ name = name.toLowerCase();
// all URL-safe characters and "@" for issue #75
if (!name.match(/^[-a-zA-Z0-9_.!~*'()@]+$/)
@@ -30,88 +32,88 @@ module.exports.validate_name = function(name) {
|| name === 'package.json'
|| name === 'favicon.ico'
) {
- return false
+ return false;
} else {
- return true
+ return true;
}
-}
+};
module.exports.is_object = function(obj) {
- return typeof(obj) === 'object' && obj !== null && !Array.isArray(obj)
-}
+ return typeof(obj) === 'object' && obj !== null && !Array.isArray(obj);
+};
module.exports.validate_metadata = function(object, name) {
- assert(module.exports.is_object(object), 'not a json object')
- assert.equal(object.name, name)
+ assert(module.exports.is_object(object), 'not a json object');
+ assert.equal(object.name, name);
if (!module.exports.is_object(object['dist-tags'])) {
- object['dist-tags'] = {}
+ object['dist-tags'] = {};
}
if (!module.exports.is_object(object['versions'])) {
- object['versions'] = {}
+ object['versions'] = {};
}
- return object
-}
+ return object;
+};
module.exports.filter_tarball_urls = function(pkg, req, config) {
function filter(_url) {
- if (!req.headers.host) return _url
+ if (!req.headers.host) return _url;
- var filename = URL.parse(_url).pathname.replace(/^.*\//, '')
+ let filename = URL.parse(_url).pathname.replace(/^.*\//, '');
if (config.url_prefix != null) {
- var result = config.url_prefix.replace(/\/$/, '')
+ var result = config.url_prefix.replace(/\/$/, '');
} else {
- var result = req.protocol + '://' + req.headers.host
+ var result = req.protocol + '://' + req.headers.host;
}
- return result + '/' + pkg.name.replace(/\//g, '%2f') + '/-/' + filename
+ return `${result}/${pkg.name.replace(/\//g, '%2f')}/-/${filename}`;
}
- for (var ver in pkg.versions) {
- var dist = pkg.versions[ver].dist
+ for (let ver in pkg.versions) {
+ let dist = pkg.versions[ver].dist;
if (dist != null && dist.tarball != null) {
- //dist.__verdaccio_orig_tarball = dist.tarball
- dist.tarball = filter(dist.tarball)
+ // dist.__verdaccio_orig_tarball = dist.tarball
+ dist.tarball = filter(dist.tarball);
}
}
- return pkg
-}
+ return pkg;
+};
module.exports.tag_version = function(data, version, tag) {
if (tag) {
if (data['dist-tags'][tag] !== version) {
if (Semver.parse(version, true)) {
// valid version - store
- data['dist-tags'][tag] = version
- return true
+ data['dist-tags'][tag] = version;
+ return true;
}
}
- Logger.logger.warn({ver: version, tag: tag}, 'ignoring bad version @{ver} in @{tag}')
+ Logger.logger.warn({ver: version, tag: tag}, 'ignoring bad version @{ver} in @{tag}');
if (tag && data['dist-tags'][tag]) {
- delete data['dist-tags'][tag]
+ delete data['dist-tags'][tag];
}
}
- return false
-}
+ return false;
+};
// gets version from a package object taking into account semver weirdness
module.exports.get_version = function(object, version) {
- if (object.versions[version] != null) return object.versions[version]
+ if (object.versions[version] != null) return object.versions[version];
try {
- version = Semver.parse(version, true)
- for (var k in object.versions) {
+ version = Semver.parse(version, true);
+ for (let k in object.versions) {
if (version.compare(Semver.parse(k, true)) === 0) {
- return object.versions[k]
+ return object.versions[k];
}
}
} catch (err) {
- return undefined
+ return undefined;
}
-}
+};
module.exports.parse_address = function parse_address(addr) {
//
@@ -129,68 +131,67 @@ module.exports.parse_address = function parse_address(addr) {
// TODO: refactor it to something more reasonable?
//
// protocol : // ( host )|( ipv6 ): port /
- var m = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(addr)
+ var m = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(addr);
if (m) return {
proto: m[2] || 'http',
- host: m[6] || m[7] || 'localhost',
- port: m[8] || '4873',
- }
+ host: m[6] || m[7] || 'localhost',
+ port: m[8] || '4873',
+ };
- var m = /^((https?):(\/\/)?)?unix:(.*)$/.exec(addr)
+ var m = /^((https?):(\/\/)?)?unix:(.*)$/.exec(addr);
if (m) return {
proto: m[2] || 'http',
- path: m[4],
- }
+ path: m[4],
+ };
- return null
-}
+ return null;
+};
// function filters out bad semver versions and sorts the array
module.exports.semver_sort = function semver_sort(array) {
return array
.filter(function(x) {
if (!Semver.parse(x, true)) {
- Logger.logger.warn( {ver: x}, 'ignoring bad version @{ver}' )
- return false
+ Logger.logger.warn( {ver: x}, 'ignoring bad version @{ver}' );
+ return false;
}
- return true
+ return true;
})
.sort(Semver.compareLoose)
- .map(String)
-}
+ .map(String);
+};
// flatten arrays of tags
-module.exports.normalize_dist_tags = function (data) {
- var sorted
+module.exports.normalize_dist_tags = function(data) {
+ let sorted;
if (!data['dist-tags'].latest) {
// overwrite latest with highest known version based on semver sort
- sorted = module.exports.semver_sort(Object.keys(data.versions))
+ sorted = module.exports.semver_sort(Object.keys(data.versions));
if (sorted && sorted.length) {
- data['dist-tags'].latest = sorted.pop()
+ data['dist-tags'].latest = sorted.pop();
}
}
- for (var tag in data['dist-tags']) {
+ for (let tag in data['dist-tags']) {
if (Array.isArray(data['dist-tags'][tag])) {
if (data['dist-tags'][tag].length) {
// sort array
- sorted = module.exports.semver_sort(data['dist-tags'][tag])
+ sorted = module.exports.semver_sort(data['dist-tags'][tag]);
if (sorted.length) {
// use highest version based on semver sort
- data['dist-tags'][tag] = sorted.pop()
+ data['dist-tags'][tag] = sorted.pop();
}
-
} else {
- delete data['dist-tags'][tag]
+ delete data['dist-tags'][tag];
}
} else if (typeof data['dist-tags'][tag] === 'string') {
if (!Semver.parse(data['dist-tags'][tag], true)) {
// if the version is invalid, delete the dist-tag entry
- delete data['dist-tags'][tag]
+ delete data['dist-tags'][tag];
}
}
}
-}
+};
diff --git a/package.json b/package.json
index d98393e0e..ea4b301ea 100644
--- a/package.json
+++ b/package.json
@@ -20,10 +20,10 @@
"async": "^2.0.1",
"body-parser": "^1.15.0",
"bunyan": "^1.8.0",
+ "chalk": "^1.1.3",
"commander": "^2.9.0",
"compression": "^1.6.1",
"cookies": "^0.6.1",
- "es6-shim": "^0.35.0",
"express": "^4.13.4",
"handlebars": "^4.0.5",
"highlight.js": "^9.3.0",
@@ -32,7 +32,7 @@
"js-yaml": "^3.6.0",
"lockfile": "^1.0.1",
"lunr": "^0.7.0",
- "minimatch": "^3.0.0",
+ "minimatch": "^3.0.2",
"mkdirp": "^0.5.1",
"pkginfo": "^0.4.0",
"readable-stream": "^2.1.2",
@@ -42,16 +42,16 @@
"unix-crypt-td-js": "^1.0.0"
},
"devDependencies": {
- "bluebird": "^3.3.5",
"browserify": "^13.0.0",
"browserify-handlebars": "^1.0.0",
- "eslint": "^2.9.0",
+ "eslint": "^3.19.0",
+ "eslint-config-google": "^0.7.1",
"grunt": "^1.0.1",
"grunt-browserify": "^5.0.0",
"grunt-cli": "^1.2.0",
"grunt-contrib-less": "^1.3.0",
"grunt-contrib-watch": "^1.0.0",
- "mocha": "^2.4.5",
+ "mocha": "^3.2.0",
"nyc": "^10.1.2",
"onclick": "^0.1.0",
"rimraf": "^2.5.2",
@@ -68,16 +68,16 @@
"server"
],
"scripts": {
- "test": "eslint . && mocha ./test/functional ./test/unit",
+ "test": "npm run lint && mocha ./test/functional ./test/unit",
"test:coverage": "nyc --reporter=html --reporter=text mocha -R spec ./test/functional ./test/unit",
- "test-travis": "eslint . && npm run test:coverage",
+ "test-travis": "npm run lint && npm run test:coverage",
"test-only": "mocha ./test/functional ./test/unit",
"lint": "eslint .",
"build-docker": "docker build -t verdaccio .",
"build-docker:rpi": "docker build -f Dockerfile.rpi -t verdaccio:rpi ."
},
"engines": {
- "node": ">=4"
+ "node": ">=4.6.1"
},
"preferGlobal": true,
"publishConfig": {
diff --git a/test/.eslintrc b/test/.eslintrc
index b3e16f8ee..04edb2ff9 100644
--- a/test/.eslintrc
+++ b/test/.eslintrc
@@ -1,5 +1,12 @@
+# vim: syntax=yaml
+
+extends: ["eslint:recommended"]
env:
node: true
mocha: true
+ es6: true
+valid-jsdoc: 0
+no-redeclare: 1
+no-console: 1
\ No newline at end of file
diff --git a/test/functional/access.js b/test/functional/access.js
index f0acddffc..e33682614 100644
--- a/test/functional/access.js
+++ b/test/functional/access.js
@@ -1,80 +1,73 @@
+'use strict';
-module.exports = function () {
- describe('access control', function () {
- var server = process.server
- var oldauth
+module.exports = function() {
+ describe('access control', function() {
+ let server = process.server;
+ let oldauth;
- before(function () {
- oldauth = server.authstr
- })
+ before(function() {
+ oldauth = server.authstr;
+ });
- after(function () {
- server.authstr = oldauth
- })
+ after(function() {
+ server.authstr = oldauth;
+ });
function check_access(auth, pkg, ok) {
- it((ok ? 'allows' : 'forbids') +' access ' + auth + ' to ' + pkg, function () {
- server.authstr = auth
- ? 'Basic '+(new Buffer(auth).toString('base64'))
- : undefined
-
- var req = server.get_package(pkg)
-
+ it((ok ? 'allows' : 'forbids') +' access ' + auth + ' to ' + pkg, function() {
+ server.authstr = auth? `Basic ${(new Buffer(auth).toString('base64'))}`: undefined;
+ let req = server.get_package(pkg);
if (ok) {
- return req.status(404)
- .body_error(/no such package available/)
+ return req.status(404).body_error(/no such package available/);
} else {
- return req.status(403)
- .body_error(/not allowed to access package/)
+ return req.status(403).body_error(/not allowed to access package/);
}
- })
+ });
}
function check_publish(auth, pkg, ok) {
- it((ok ? 'allows' : 'forbids') + ' publish ' + auth + ' to ' + pkg, function () {
- server.authstr = auth
- ? 'Basic '+(new Buffer(auth).toString('base64'))
- : undefined
-
- var req = server.put_package(pkg, require('./lib/package')(pkg))
-
+ it(`${(ok ? 'allows' : 'forbids')} publish ${auth} to ${pkg}`, function() {
+ server.authstr = auth? `Basic ${(new Buffer(auth).toString('base64'))}`: undefined;
+ let req = server.put_package(pkg, require('./lib/package')(pkg));
if (ok) {
- return req.status(404)
- .body_error(/this package cannot be added/)
+ return req.status(404).body_error(/this package cannot be added/);
} else {
- return req.status(403)
- .body_error(/not allowed to publish package/)
+ return req.status(403).body_error(/not allowed to publish package/);
}
- })
+ });
}
+ const badPass = 'test:badpass';
+ const testPass = 'test:test';
+ const testAccessOnly = 'test-access-only';
+ const testPublishOnly = 'test-publish-only';
+ const testOnlyTest = 'test-only-test';
+ const testOnlyAuth = 'test-only-auth';
+ check_access(testPass, testAccessOnly, true);
+ check_access(undefined, testAccessOnly, true);
+ check_access(badPass, testAccessOnly, true);
+ check_publish(testPass, testAccessOnly, false);
+ check_publish(undefined, testAccessOnly, false);
+ check_publish(badPass, testAccessOnly, false);
- check_access('test:test', 'test-access-only', true)
- check_access(undefined, 'test-access-only', true)
- check_access('test:badpass', 'test-access-only', true)
- check_publish('test:test', 'test-access-only', false)
- check_publish(undefined, 'test-access-only', false)
- check_publish('test:badpass', 'test-access-only', false)
+ check_access(testPass, testPublishOnly, false);
+ check_access(undefined, testPublishOnly, false);
+ check_access(badPass, testPublishOnly, false);
+ check_publish(testPass, testPublishOnly, true);
+ check_publish(undefined, testPublishOnly, true);
+ check_publish(badPass, testPublishOnly, true);
- check_access('test:test', 'test-publish-only', false)
- check_access(undefined, 'test-publish-only', false)
- check_access('test:badpass', 'test-publish-only', false)
- check_publish('test:test', 'test-publish-only', true)
- check_publish(undefined, 'test-publish-only', true)
- check_publish('test:badpass', 'test-publish-only', true)
-
- check_access('test:test', 'test-only-test', true)
- check_access(undefined, 'test-only-test', false)
- check_access('test:badpass', 'test-only-test', false)
- check_publish('test:test', 'test-only-test', true)
- check_publish(undefined, 'test-only-test', false)
- check_publish('test:badpass', 'test-only-test', false)
-
- check_access('test:test', 'test-only-auth', true)
- check_access(undefined, 'test-only-auth', false)
- check_access('test:badpass', 'test-only-auth', false)
- check_publish('test:test', 'test-only-auth', true)
- check_publish(undefined, 'test-only-auth', false)
- check_publish('test:badpass', 'test-only-auth', false)
- })
-}
+ check_access(testPass, testOnlyTest, true);
+ check_access(undefined, testOnlyTest, false);
+ check_access(badPass, testOnlyTest, false);
+ check_publish(testPass, testOnlyTest, true);
+ check_publish(undefined, testOnlyTest, false);
+ check_publish(badPass, testOnlyTest, false);
+ check_access(testPass, testOnlyAuth, true);
+ check_access(undefined, testOnlyAuth, false);
+ check_access(badPass, testOnlyAuth, false);
+ check_publish(testPass, testOnlyAuth, true);
+ check_publish(undefined, testOnlyAuth, false);
+ check_publish(badPass, testOnlyAuth, false);
+ });
+};
diff --git a/test/functional/addtag.js b/test/functional/addtag.js
index 6303c6370..1e2445abe 100644
--- a/test/functional/addtag.js
+++ b/test/functional/addtag.js
@@ -1,46 +1,47 @@
+'use strict';
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
-module.exports = function () {
- var server = process.server
+module.exports = function() {
+ let server = process.server;
- it('add tag - 404', function () {
- return server.add_tag('testpkg-tag', 'tagtagtag', '0.0.1')
- .status(404)
- .body_error(/no such package/)
- })
+ it('add tag - 404', function() {
+ return server.add_tag('testpkg-tag', 'tagtagtag', '0.0.1').status(404).body_error(/no such package/);
+ });
describe('addtag', function() {
- before(function () {
+ before(function() {
return server.put_package('testpkg-tag', eval(
- '(' + readfile('fixtures/publish.json5')
- .toString('utf8')
- .replace(/__NAME__/g, 'testpkg-tag')
- .replace(/__VERSION__/g, '0.0.1')
- + ')'
- )).status(201)
- })
+ '(' + readfile('fixtures/publish.json5')
+ .toString('utf8')
+ .replace(/__NAME__/g, 'testpkg-tag')
+ .replace(/__VERSION__/g, '0.0.1')
+ + ')'
+ )).status(201);
+ });
- it('add testpkg-tag', function(){})
+ it('add testpkg-tag', function() {
+ // TODO: ?
+ });
- it('add tag - bad ver', function () {
+ it('add tag - bad ver', function() {
return server.add_tag('testpkg-tag', 'tagtagtag', '0.0.1-x')
- .status(404)
- .body_error(/version doesn't exist/)
- })
+ .status(404)
+ .body_error(/version doesn't exist/);
+ });
- it('add tag - bad tag', function () {
+ it('add tag - bad tag', function() {
return server.add_tag('testpkg-tag', 'tag/tag/tag', '0.0.1-x')
- .status(403)
- .body_error(/invalid tag/)
- })
+ .status(403)
+ .body_error(/invalid tag/);
+ });
- it('add tag - good', function () {
+ it('add tag - good', function() {
return server.add_tag('testpkg-tag', 'tagtagtag', '0.0.1')
- .status(201)
- .body_ok(/tagged/)
- })
- })
-}
+ .status(201)
+ .body_ok(/tagged/);
+ });
+ });
+};
diff --git a/test/functional/adduser.js b/test/functional/adduser.js
index b0c6bcf53..5fd38e39f 100644
--- a/test/functional/adduser.js
+++ b/test/functional/adduser.js
@@ -1,47 +1,49 @@
-var Server = require('./lib/server')
-var fs = require('fs')
-var path = require('path')
+'use strict';
+
+const Server = require('./lib/server');
+const fs = require('fs');
+const path = require('path');
module.exports = function() {
- var server = new Server('http://localhost:55551/')
+ const server = new Server('http://localhost:55551/');
describe('adduser', function() {
- var user = String(Math.random())
- var pass = String(Math.random())
- before(function () {
+ const user = String(Math.random());
+ const pass = String(Math.random());
+ before(function() {
return server.auth(user, pass)
.status(201)
- .body_ok(/user .* created/)
- })
+ .body_ok(/user .* created/);
+ });
- it('creating new user', function(){})
+ it('creating new user', function() {});
- it('should log in', function () {
+ it('should log in', function() {
return server.auth(user, pass)
.status(201)
- .body_ok(/you are authenticated as/)
- })
+ .body_ok(/you are authenticated as/);
+ });
- it('should not register more users', function () {
+ it('should not register more users', function() {
return server.auth(String(Math.random()), String(Math.random()))
.status(409)
- .body_error(/maximum amount of users reached/)
- })
- })
+ .body_error(/maximum amount of users reached/);
+ });
+ });
describe('adduser created with htpasswd', function() {
- var user = 'preexisting'
- var pass = 'preexisting'
- before(function () {
+ let user = 'preexisting';
+ let pass = 'preexisting';
+ before(function() {
return fs.appendFileSync(
path.join(__dirname, 'test-storage', '.htpasswd'),
'preexisting:$apr1$4YSboUa9$yVKjE7.PxIOuK3M4D7VjX.'
- )
- })
- it('should log in', function () {
+ );
+ });
+ it('should log in', function() {
return server.auth(user, pass)
.status(201)
- .body_ok(/you are authenticated as/)
- })
- })
-}
+ .body_ok(/you are authenticated as/);
+ });
+ });
+};
diff --git a/test/functional/basic.js b/test/functional/basic.js
index 542c5fa9c..6aa4c9d73 100644
--- a/test/functional/basic.js
+++ b/test/functional/basic.js
@@ -1,119 +1,121 @@
-require('./lib/startup')
+'use strict';
-var assert = require('assert')
-var crypto = require('crypto')
+require('./lib/startup');
+
+const assert = require('assert');
+const crypto = require('crypto');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
-module.exports = function () {
- var server = process.server
- var server2 = process.server2
+module.exports = function() {
+ let server = process.server;
+ let server2 = process.server2;
- it('trying to fetch non-existent package', function () {
- return server.get_package('testpkg').status(404).body_error(/no such package/)
- })
+ it('trying to fetch non-existent package', function() {
+ return server.get_package('testpkg').status(404).body_error(/no such package/);
+ });
- describe('testpkg', function () {
- before(function () {
- return server.add_package('testpkg')
- })
+ describe('testpkg', function() {
+ before(function() {
+ return server.add_package('testpkg');
+ });
- it('creating new package', function (){/* test for before() */})
+ it('creating new package', function() {/* test for before() */});
- it('downloading non-existent tarball', function () {
- return server.get_tarball('testpkg', 'blahblah').status(404).body_error(/no such file/)
- })
+ it('downloading non-existent tarball', function() {
+ return server.get_tarball('testpkg', 'blahblah').status(404).body_error(/no such file/);
+ });
- it('uploading incomplete tarball', function () {
- return server.put_tarball_incomplete('testpkg', 'blahblah1', readfile('fixtures/binary'), 3000)
- })
+ it('uploading incomplete tarball', function() {
+ return server.put_tarball_incomplete('testpkg', 'blahblah1', readfile('fixtures/binary'), 3000);
+ });
- describe('tarball', function () {
- before(function () {
+ describe('tarball', function() {
+ before(function() {
return server.put_tarball('testpkg', 'blahblah', readfile('fixtures/binary'))
.status(201)
- .body_ok(/.*/)
- })
+ .body_ok(/.*/);
+ });
- it('uploading new tarball', function (){/* test for before() */})
+ it('uploading new tarball', function() {/* test for before() */});
- it('downloading newly created tarball', function () {
+ it('downloading newly created tarball', function() {
return server.get_tarball('testpkg', 'blahblah')
.status(200)
- .then(function (body) {
- assert.deepEqual(body, readfile('fixtures/binary'))
- })
- })
+ .then(function(body) {
+ assert.deepEqual(body, readfile('fixtures/binary'));
+ });
+ });
- it('uploading new package version (bad sha)', function () {
- var pkg = require('./lib/package')('testpkg')
- pkg.dist.shasum = crypto.createHash('sha1').update('fake').digest('hex')
+ it('uploading new package version (bad sha)', function() {
+ let pkg = require('./lib/package')('testpkg');
+ pkg.dist.shasum = crypto.createHash('sha1').update('fake').digest('hex');
return server.put_version('testpkg', '0.0.1', pkg)
.status(400)
- .body_error(/shasum error/)
- })
+ .body_error(/shasum error/);
+ });
- describe('version', function () {
- before(function () {
- var pkg = require('./lib/package')('testpkg')
- pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex')
+ describe('version', function() {
+ before(function() {
+ let pkg = require('./lib/package')('testpkg');
+ pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server.put_version('testpkg', '0.0.1', pkg)
.status(201)
- .body_ok(/published/)
- })
+ .body_ok(/published/);
+ });
- it('uploading new package version', function (){/* test for before() */})
+ it('uploading new package version', function() {/* test for before() */});
- it('downloading newly created package', function () {
+ it('downloading newly created package', function() {
return server.get_package('testpkg')
.status(200)
- .then(function (body) {
- assert.equal(body.name, 'testpkg')
- assert.equal(body.versions['0.0.1'].name, 'testpkg')
- assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/testpkg/-/blahblah')
- assert.deepEqual(body['dist-tags'], {latest: '0.0.1'})
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, 'testpkg');
+ assert.equal(body.versions['0.0.1'].name, 'testpkg');
+ assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/testpkg/-/blahblah');
+ assert.deepEqual(body['dist-tags'], {latest: '0.0.1'});
+ });
+ });
- it('downloading package via server2', function () {
+ it('downloading package via server2', function() {
return server2.get_package('testpkg')
.status(200)
- .then(function (body) {
- assert.equal(body.name, 'testpkg')
- assert.equal(body.versions['0.0.1'].name, 'testpkg')
- assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55552/testpkg/-/blahblah')
- assert.deepEqual(body['dist-tags'], {latest: '0.0.1'})
- })
- })
- })
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, 'testpkg');
+ assert.equal(body.versions['0.0.1'].name, 'testpkg');
+ assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55552/testpkg/-/blahblah');
+ assert.deepEqual(body['dist-tags'], {latest: '0.0.1'});
+ });
+ });
+ });
+ });
+ });
- it('uploading new package version for bad pkg', function () {
+ it('uploading new package version for bad pkg', function() {
return server.put_version('testpxg', '0.0.1', require('./lib/package')('testpxg'))
.status(404)
- .body_error(/no such package/)
- })
+ .body_error(/no such package/);
+ });
- it('doubleerr test', function () {
+ it('doubleerr test', function() {
return server.put_tarball('testfwd2', 'blahblah', readfile('fixtures/binary'))
.status(404)
- .body_error(/no such/)
- })
+ .body_error(/no such/);
+ });
- it('publishing package / bad ro uplink', function () {
+ it('publishing package / bad ro uplink', function() {
return server.put_package('baduplink', require('./lib/package')('baduplink'))
.status(503)
- .body_error(/one of the uplinks is down, refuse to publish/)
- })
+ .body_error(/one of the uplinks is down, refuse to publish/);
+ });
- it('who am I?', function () {
- return server.whoami().then(function (username) {
- assert.equal(username, 'test')
- })
- })
-}
+ it('who am I?', function() {
+ return server.whoami().then(function(username) {
+ assert.equal(username, 'test');
+ });
+ });
+};
diff --git a/test/functional/gh29.js b/test/functional/gh29.js
index f130c84c4..a04b76616 100644
--- a/test/functional/gh29.js
+++ b/test/functional/gh29.js
@@ -1,64 +1,66 @@
-var assert = require('assert')
-var crypto = require('crypto')
+'use strict';
+
+const assert = require('assert');
+const crypto = require('crypto');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
module.exports = function() {
- var server = process.server
- var server2 = process.server2
+ let server = process.server;
+ let server2 = process.server2;
- it('downloading non-existent tarball #1 / srv2', function () {
+ it('downloading non-existent tarball #1 / srv2', function() {
return server2.get_tarball('testpkg-gh29', 'blahblah')
.status(404)
- .body_error(/no such package/)
- })
+ .body_error(/no such package/);
+ });
describe('pkg-gh29', function() {
- before(function () {
+ before(function() {
return server.put_package('testpkg-gh29', require('./lib/package')('testpkg-gh29'))
.status(201)
- .body_ok(/created new package/)
- })
+ .body_ok(/created new package/);
+ });
- it('creating new package / srv1', function(){})
+ it('creating new package / srv1', function() {});
- it('downloading non-existent tarball #2 / srv2', function () {
+ it('downloading non-existent tarball #2 / srv2', function() {
return server2.get_tarball('testpkg-gh29', 'blahblah')
.status(404)
- .body_error(/no such file/)
- })
+ .body_error(/no such file/);
+ });
describe('tarball', function() {
- before(function () {
+ before(function() {
return server.put_tarball('testpkg-gh29', 'blahblah', readfile('fixtures/binary'))
.status(201)
- .body_ok(/.*/)
- })
+ .body_ok(/.*/);
+ });
- it('uploading new tarball / srv1', function(){})
+ it('uploading new tarball / srv1', function() {});
describe('pkg version', function() {
- before(function () {
- var pkg = require('./lib/package')('testpkg-gh29')
- pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex')
+ before(function() {
+ let pkg = require('./lib/package')('testpkg-gh29');
+ pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server.put_version('testpkg-gh29', '0.0.1', pkg)
.status(201)
- .body_ok(/published/)
- })
+ .body_ok(/published/);
+ });
- it('uploading new package version / srv1', function(){})
+ it('uploading new package version / srv1', function() {});
- it('downloading newly created tarball / srv2', function () {
+ it('downloading newly created tarball / srv2', function() {
return server2.get_tarball('testpkg-gh29', 'blahblah')
.status(200)
- .then(function (body) {
- assert.deepEqual(body, readfile('fixtures/binary'))
- })
- })
- })
- })
- })
-}
+ .then(function(body) {
+ assert.deepEqual(body, readfile('fixtures/binary'));
+ });
+ });
+ });
+ });
+ });
+};
diff --git a/test/functional/gzip.js b/test/functional/gzip.js
index 64fbf2e6b..90063c5dc 100644
--- a/test/functional/gzip.js
+++ b/test/functional/gzip.js
@@ -1,70 +1,71 @@
-require('./lib/startup')
+'use strict';
-var assert = require('assert')
-var Promise = require('bluebird')
+require('./lib/startup');
+
+let assert = require('assert');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
module.exports = function() {
- var server = process.server
- var express = process.express
+ let server = process.server;
+ let express = process.express;
describe('testexp_gzip', function() {
before(function() {
express.get('/testexp_gzip', function(req, res) {
- var x = eval(
+ let x = eval(
'(' + readfile('fixtures/publish.json5')
.toString('utf8')
.replace(/__NAME__/g, 'testexp_gzip')
.replace(/__VERSION__/g, '0.0.1')
+ ')'
- )
+ );
// overcoming compress threshold
- x.versions['0.0.2'] = x.versions['0.0.1']
- x.versions['0.0.3'] = x.versions['0.0.1']
- x.versions['0.0.4'] = x.versions['0.0.1']
- x.versions['0.0.5'] = x.versions['0.0.1']
- x.versions['0.0.6'] = x.versions['0.0.1']
- x.versions['0.0.7'] = x.versions['0.0.1']
- x.versions['0.0.8'] = x.versions['0.0.1']
- x.versions['0.0.9'] = x.versions['0.0.1']
+ x.versions['0.0.2'] = x.versions['0.0.1'];
+ x.versions['0.0.3'] = x.versions['0.0.1'];
+ x.versions['0.0.4'] = x.versions['0.0.1'];
+ x.versions['0.0.5'] = x.versions['0.0.1'];
+ x.versions['0.0.6'] = x.versions['0.0.1'];
+ x.versions['0.0.7'] = x.versions['0.0.1'];
+ x.versions['0.0.8'] = x.versions['0.0.1'];
+ x.versions['0.0.9'] = x.versions['0.0.1'];
require('zlib').gzip(JSON.stringify(x), function(err, buf) {
- assert.equal(err, null)
- assert.equal(req.headers['accept-encoding'], 'gzip')
- res.header('content-encoding', 'gzip')
- res.send(buf)
- })
- })
+ assert.equal(err, null);
+ assert.equal(req.headers['accept-encoding'], 'gzip');
+ res.header('content-encoding', 'gzip');
+ res.send(buf);
+ });
+ });
express.get('/testexp_baddata', function(req, res) {
- assert.equal(req.headers['accept-encoding'], 'gzip')
- res.header('content-encoding', 'gzip')
- res.send(new Buffer([1,2,3,4,5,6,7,7,6,5,4,3,2,1]))
- })
- })
+ assert.equal(req.headers['accept-encoding'], 'gzip');
+ res.header('content-encoding', 'gzip');
+ res.send(new Buffer([1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1]));
+ });
+ });
- it('should not fail on bad gzip', function () {
+ it('should not fail on bad gzip', function() {
return server.get_package('testexp_baddata')
- .status(404)
- })
+ .status(404);
+ });
- it('should understand gzipped data from uplink', function () {
+ it('should understand gzipped data from uplink', function() {
return server.get_package('testexp_gzip')
.status(200)
- .response(function (res) {
- assert.equal(res.headers['content-encoding'], undefined)
+ .response(function(res) {
+ assert.equal(res.headers['content-encoding'], undefined);
})
- .then(function (body) {
- assert.equal(body.name, 'testexp_gzip')
- assert.equal(Object.keys(body.versions).length, 9)
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, 'testexp_gzip');
+ assert.equal(Object.keys(body.versions).length, 9);
+ });
+ });
- it('should serve gzipped data', function () {
+ it('should serve gzipped data', function() {
return server.request({
uri: '/testexp_gzip',
encoding: null,
@@ -73,25 +74,25 @@ module.exports = function() {
},
json: false,
}).status(200)
- .response(function (res) {
- assert.equal(res.headers['content-encoding'], 'gzip')
+ .response(function(res) {
+ assert.equal(res.headers['content-encoding'], 'gzip');
})
- .then(function (body) {
+ .then(function(body) {
assert.throws(function() {
- JSON.parse(body.toString('utf8'))
- })
+ JSON.parse(body.toString('utf8'));
+ });
- return new Promise(function (resolve) {
+ return new Promise(function(resolve) {
require('zlib').gunzip(body, function(err, buf) {
- assert.equal(err, null)
- body = JSON.parse(buf)
- assert.equal(body.name, 'testexp_gzip')
- assert.equal(Object.keys(body.versions).length, 9)
- resolve()
- })
- })
- })
- })
- })
-}
+ assert.equal(err, null);
+ body = JSON.parse(buf);
+ assert.equal(body.name, 'testexp_gzip');
+ assert.equal(Object.keys(body.versions).length, 9);
+ resolve();
+ });
+ });
+ });
+ });
+ });
+};
diff --git a/test/functional/incomplete.js b/test/functional/incomplete.js
index f093de2ac..4e76f04d7 100644
--- a/test/functional/incomplete.js
+++ b/test/functional/incomplete.js
@@ -1,67 +1,71 @@
-var assert = require('assert')
+'use strict';
+
+let assert = require('assert');
module.exports = function() {
- var server = process.server
- var express = process.express
+ let server = process.server;
+ let express = process.express;
describe('Incomplete', function() {
before(function() {
express.get('/testexp-incomplete', function(_, res) {
res.send({
- "name": "testexp-incomplete",
- "versions": {
- "0.1.0": {
- "name": "testexp_tags",
- "version": "0.1.0",
- "dist": {
- "shasum": "fake",
- "tarball": "http://localhost:55550/testexp-incomplete/-/content-length.tar.gz"
- }
+ 'name': 'testexp-incomplete',
+ 'versions': {
+ '0.1.0': {
+ 'name': 'testexp_tags',
+ 'version': '0.1.0',
+ 'dist': {
+ 'shasum': 'fake',
+ 'tarball': 'http://localhost:55550/testexp-incomplete/-/content-length.tar.gz',
+ },
},
- "0.1.1": {
- "name": "testexp_tags",
- "version": "0.1.1",
- "dist": {
- "shasum": "fake",
- "tarball": "http://localhost:55550/testexp-incomplete/-/chunked.tar.gz"
- }
- }
- }
- })
- })
+ '0.1.1': {
+ 'name': 'testexp_tags',
+ 'version': '0.1.1',
+ 'dist': {
+ 'shasum': 'fake',
+ 'tarball': 'http://localhost:55550/testexp-incomplete/-/chunked.tar.gz',
+ },
+ },
+ },
+ });
+ });
})
- ;[ 'content-length', 'chunked' ].forEach(function(type) {
+ ;['content-length', 'chunked'].forEach(function(type) {
it('should not store tarballs / ' + type, function(_cb) {
- var called
+ let called;
express.get('/testexp-incomplete/-/'+type+'.tar.gz', function(_, res) {
- if (called) return res.socket.destroy()
- called = true
- if (type !== 'chunked') res.header('content-length', 1e6)
- res.write('test test test\n')
+ if (called) return res.socket.destroy();
+ called = true;
+ if (type !== 'chunked') res.header('content-length', 1e6);
+ res.write('test test test\n');
setTimeout(function() {
- res.socket.write('200\nsss\n')
- res.socket.destroy()
- cb()
- }, 10)
- })
+ res.socket.write('200\nsss\n');
+ res.socket.destroy();
+ cb();
+ }, 10);
+ });
- server.request({ uri: '/testexp-incomplete/-/'+type+'.tar.gz' })
+ server.request({uri: '/testexp-incomplete/-/'+type+'.tar.gz'})
.status(200)
- .response(function (res) {
- if (type !== 'chunked') assert.equal(res.headers['content-length'], 1e6)
- })
- .then(function (body) {
- assert(body.match(/test test test/))
+ .response(function(res) {
+ if (type !== 'chunked') assert.equal(res.headers['content-length'], 1e6);
})
+ .then(function(body) {
+ assert(body.match(/test test test/));
+ });
function cb() {
- server.request({ uri: '/testexp-incomplete/-/'+type+'.tar.gz' })
+ server.request({uri: '/testexp-incomplete/-/'+type+'.tar.gz'})
.body_error('internal server error')
- .then(function () { _cb() })
+ .then(function() {
+ _cb();
+});
}
- })
- })
- })
-}
+ });
+ });
+ });
+};
diff --git a/test/functional/index.js b/test/functional/index.js
index 34df7fd1c..18b9daa47 100644
--- a/test/functional/index.js
+++ b/test/functional/index.js
@@ -1,88 +1,94 @@
-//require('es6-shim')
-require('./lib/startup')
-var Promise = require('bluebird')
+'use strict';
-var assert = require('assert')
-var async = require('async')
-var exec = require('child_process').exec
+require('./lib/startup');
+
+const assert = require('assert');
+const exec = require('child_process').exec;
describe('Func', function() {
- var server = process.server
- var server2 = process.server2
+ const server = process.server;
+ const server2 = process.server2;
- before(function (cb) {
- async.parallel([
- function (cb) {
- require('./lib/startup').start('./test-storage', './config-1.yaml', cb)
- },
- function (cb) {
- require('./lib/startup').start('./test-storage2', './config-2.yaml', cb)
- },
- ], cb)
- })
+ before(function(done) {
+ Promise.all([
+ require('./lib/startup').start('./test-storage', './config-1.yaml'),
+ require('./lib/startup').start('./test-storage2', './config-2.yaml'),
+ ]).then(() => {
+ done();
+ });
+ });
before(function() {
- return Promise.all([ server, server2 ].map(function(server) {
- return server.debug().status(200).then(function (body) {
- server.pid = body.pid
-
- return new Promise(function (resolve, reject) {
+ return Promise.all([server, server2].map(function(server) {
+ return server.debug().status(200).then(function(body) {
+ server.pid = body.pid;
+ return new Promise(function(resolve, reject) {
exec('lsof -p ' + Number(server.pid), function(err, result) {
- assert.equal(err, null)
- server.fdlist = result.replace(/ +/g, ' ')
- resolve()
- })
- })
- })
- }))
- })
+ assert.equal(err, null);
+ server.fdlist = result.replace(/ +/g, ' ');
+ resolve();
+ });
+ });
+ });
+ }));
+ });
before(function auth() {
- return Promise.all([ server, server2 ].map(function(server, cb) {
- return server.auth('test', 'test').status(201).body_ok(/'test'/)
- }))
- })
+ return Promise.all([server, server2].map(function(server, cb) {
+ return server.auth('test', 'test').status(201).body_ok(/'test'/);
+ }));
+ });
- it('authenticate', function(){/* test for before() */})
+ it('authenticate', function() {/* test for before() */});
- require('./access')()
- require('./basic')()
- require('./gh29')()
- require('./tags')()
- require('./gzip')()
- require('./incomplete')()
- require('./mirror')()
- require('./newnpmreg')()
- require('./nullstorage')()
- require('./race')()
- require('./racycrash')()
- require('./scoped')()
- require('./security')()
- require('./adduser')()
- require('./logout')()
- require('./addtag')()
- require('./plugins')()
+ require('./access')();
+ require('./basic')();
+ require('./gh29')();
+ require('./tags')();
+ require('./gzip')();
+ require('./incomplete')();
+ require('./mirror')();
+ require('./newnpmreg')();
+ require('./nullstorage')();
+ require('./race')();
+ require('./racycrash')();
+ require('./scoped')();
+ require('./security')();
+ require('./adduser')();
+ require('./logout')();
+ require('./addtag')();
+ require('./plugins')();
- after(function (cb) {
- async.map([ server, server2 ], function(server, cb) {
- exec('lsof -p ' + Number(server.pid), function(err, result) {
- assert.equal(err, null)
- result = result.split('\n').filter(function(q) {
- if (q.match(/TCP .*->.* \(ESTABLISHED\)/)) return false
- if (q.match(/\/libcrypt-[^\/]+\.so/)) return false
- if (q.match(/\/node_modules\/crypt3\/build\/Release/)) return false
- return true
- }).join('\n').replace(/ +/g, ' ')
+ after(function(done) {
+ const check = (server) => {
+ return new Promise(function(resolve, reject) {
+ exec('lsof -p ' + parseInt(server.pid, 10), function(err, result) {
+ if (err) {
+ reject();
+ } else {
+ result = result.split('\n').filter(function(q) {
+ if (q.match(/TCP .*->.* \(ESTABLISHED\)/)) return false;
+ if (q.match(/\/libcrypt-[^\/]+\.so/)) return false;
+ if (q.match(/\/node_modules\/crypt3\/build\/Release/)) return false;
+ return true;
+ }).join('\n').replace(/ +/g, ' ');
+ assert.equal(server.fdlist, result);
+ resolve();
+ }
+ });
+ });
+ };
+ Promise.all([check(server), check(server2)]).then(function() {
+ done();
+ }, (reason) => {
+ assert.equal(reason, null);
+ done();
+ });
+ });
+});
- assert.equal(server.fdlist, result)
- cb()
- })
- }, cb)
- })
-})
-
-process.on('unhandledRejection', function (err) {
- process.nextTick(function () {
- throw err
- })
-})
+process.on('unhandledRejection', function(err) {
+ process.nextTick(function() {
+ throw err;
+ });
+});
diff --git a/test/functional/lib/package.js b/test/functional/lib/package.js
index 8e0156639..0c12e864d 100644
--- a/test/functional/lib/package.js
+++ b/test/functional/lib/package.js
@@ -1,12 +1,11 @@
-
module.exports = function(name, version) {
return {
- "name": name,
- "version": version || "0.0.0",
- "dist": {
- "shasum": "fake",
- "tarball": "http://localhost:55551/"+encodeURIComponent(name)+"/-/blahblah"
- }
- }
-}
+ name,
+ version: version || '0.0.0',
+ dist: {
+ shasum: 'fake',
+ tarball: `http://localhost:55551/${encodeURIComponent(name)}/-/blahblah`,
+ },
+ };
+};
diff --git a/test/functional/lib/server.js b/test/functional/lib/server.js
index 0a720b14c..7a946a651 100644
--- a/test/functional/lib/server.js
+++ b/test/functional/lib/server.js
@@ -1,21 +1,22 @@
-var assert = require('assert')
-var request = require('./smart_request')
-var Promise = require('bluebird')
+'use strict';
+
+const assert = require('assert');
+const request = require('./smart_request');
function Server(url) {
- var self = Object.create(Server.prototype)
- self.url = url.replace(/\/$/, '')
- self.userAgent = 'node/v0.10.8 linux x64'
- self.authstr = 'Basic '+(new Buffer('test:test')).toString('base64')
- return self
+ let self = Object.create(Server.prototype);
+ self.url = url.replace(/\/$/, '');
+ self.userAgent = 'node/v0.10.8 linux x64';
+ self.authstr = 'Basic '+(new Buffer('test:test')).toString('base64');
+ return self;
}
Server.prototype.request = function(options) {
- assert(options.uri)
- var headers = options.headers || {}
- headers.accept = headers.accept || 'application/json'
- headers['user-agent'] = headers['user-agent'] || this.userAgent
- headers.authorization = headers.authorization || this.authstr
+ assert(options.uri);
+ let headers = options.headers || {};
+ headers.accept = headers.accept || 'application/json';
+ headers['user-agent'] = headers['user-agent'] || this.userAgent;
+ headers.authorization = headers.authorization || this.authstr;
return request({
url: this.url + options.uri,
@@ -23,11 +24,11 @@ Server.prototype.request = function(options) {
headers: headers,
encoding: options.encoding,
json: options.json != null ? options.json : true,
- })
-}
+ });
+};
Server.prototype.auth = function(user, pass) {
- this.authstr = 'Basic '+(new Buffer(user+':'+pass)).toString('base64')
+ this.authstr = 'Basic '+(new Buffer(user+':'+pass)).toString('base64');
return this.request({
uri: '/-/user/org.couchdb.user:'+encodeURIComponent(user)+'/-rev/undefined',
method: 'PUT',
@@ -39,76 +40,76 @@ Server.prototype.auth = function(user, pass) {
type: 'user',
roles: [],
date: new Date(),
- }
- })
-}
+ },
+ });
+};
Server.prototype.logout = function(token) {
return this.request({
uri: '/-/user/token/'+encodeURIComponent(token),
- method: 'DELETE'
- })
-}
+ method: 'DELETE',
+ });
+};
Server.prototype.get_package = function(name) {
return this.request({
uri: '/'+encodeURIComponent(name),
method: 'GET',
- })
-}
+ });
+};
Server.prototype.put_package = function(name, data) {
- if (typeof(data) === 'object' && !Buffer.isBuffer(data)) data = JSON.stringify(data)
+ if (typeof(data) === 'object' && !Buffer.isBuffer(data)) data = JSON.stringify(data);
return this.request({
uri: '/'+encodeURIComponent(name),
method: 'PUT',
headers: {
- 'content-type': 'application/json'
+ 'content-type': 'application/json',
},
- }).send(data)
-}
+ }).send(data);
+};
Server.prototype.put_version = function(name, version, data) {
- if (typeof(data) === 'object' && !Buffer.isBuffer(data)) data = JSON.stringify(data)
+ if (typeof(data) === 'object' && !Buffer.isBuffer(data)) data = JSON.stringify(data);
return this.request({
uri: '/'+encodeURIComponent(name)+'/'+encodeURIComponent(version)+'/-tag/latest',
method: 'PUT',
headers: {
- 'content-type': 'application/json'
+ 'content-type': 'application/json',
},
- }).send(data)
-}
+ }).send(data);
+};
Server.prototype.get_tarball = function(name, filename) {
return this.request({
uri: '/'+encodeURIComponent(name)+'/-/'+encodeURIComponent(filename),
method: 'GET',
- encoding: null
- })
-}
+ encoding: null,
+ });
+};
Server.prototype.put_tarball = function(name, filename, data) {
return this.request({
uri: '/'+encodeURIComponent(name)+'/-/'+encodeURIComponent(filename)+'/whatever',
method: 'PUT',
headers: {
- 'content-type': 'application/octet-stream'
+ 'content-type': 'application/octet-stream',
},
- }).send(data)
-}
+ }).send(data);
+};
Server.prototype.add_tag = function(name, tag, version) {
return this.request({
uri: '/'+encodeURIComponent(name)+'/'+encodeURIComponent(tag),
method: 'PUT',
headers: {
- 'content-type': 'application/json'
+ 'content-type': 'application/json',
},
- }).send(JSON.stringify(version))
-}
+ }).send(JSON.stringify(version));
+};
Server.prototype.put_tarball_incomplete = function(name, filename, data, size, cb) {
- var promise = this.request({
+ let promise = this.request({
uri: '/'+encodeURIComponent(name)+'/-/'+encodeURIComponent(filename)+'/whatever',
method: 'PUT',
headers: {
@@ -116,51 +117,53 @@ Server.prototype.put_tarball_incomplete = function(name, filename, data, size, c
'content-length': size,
},
timeout: 1000,
- })
+ });
- promise.request(function (req) {
- req.write(data)
+ promise.request(function(req) {
+ req.write(data);
setTimeout(function() {
- req.req.abort()
- }, 20)
- })
+ req.req.abort();
+ }, 20);
+ });
- return new Promise(function (resolve, reject) {
+ return new Promise(function(resolve, reject) {
promise
.then(function() {
- reject(Error('no error'))
+ reject(Error('no error'));
})
.catch(function(err) {
if (err.code === 'ECONNRESET') {
- resolve()
+ resolve();
} else {
- reject(err)
+ reject(err);
}
- })
- })
-}
+ });
+ });
+};
Server.prototype.add_package = function(name) {
return this.put_package(name, require('./package')(name))
.status(201)
- .body_ok('created new package')
-}
+ .body_ok('created new package');
+};
Server.prototype.whoami = function() {
- return this.request({ uri:'/-/whoami' })
+ return this.request({uri: '/-/whoami'})
.status(200)
- .then(function(x) { return x.username })
-}
+ .then(function(x) {
+ return x.username;
+});
+};
Server.prototype.debug = function() {
return this.request({
uri: '/-/_debug',
method: 'GET',
headers: {
- 'content-type': 'application/json'
+ 'content-type': 'application/json',
},
- })
-}
+ });
+};
-module.exports = Server
+module.exports = Server;
diff --git a/test/functional/lib/smart_request.js b/test/functional/lib/smart_request.js
index bae6022e5..733e5ee8e 100644
--- a/test/functional/lib/smart_request.js
+++ b/test/functional/lib/smart_request.js
@@ -1,104 +1,104 @@
+'use strict';
-var assert = require('assert')
-var request = require('request')
-var Promise = require('bluebird')
-var sym = Symbol('smart_request_data')
+const assert = require('assert');
+const request = require('request');
+const sym = Symbol('smart_request_data');
function smart_request(options) {
- var self = {}
- self[sym] = {}
- self[sym].error = Error()
- Error.captureStackTrace(self[sym].error, smart_request)
+ let self = {};
+ self[sym] = {};
+ self[sym].error = Error();
+ Error.captureStackTrace(self[sym].error, smart_request);
- var result = new Promise(function (resolve, reject) {
- self[sym].request = request(options, function (err, res, body) {
- if (err) return reject(err)
- self[sym].response = res
- resolve(body)
- })
- })
+ let result = new Promise(function(resolve, reject) {
+ self[sym].request = request(options, function(err, res, body) {
+ if (err) return reject(err);
+ self[sym].response = res;
+ resolve(body);
+ });
+ });
- return extend(self, result)
+ return extend(self, result);
}
function extend(self, promise) {
- promise[sym] = self[sym]
- Object.setPrototypeOf(promise, extensions)
- return promise
+ promise[sym] = self[sym];
+ Object.setPrototypeOf(promise, extensions);
+ return promise;
}
-var extensions = Object.create(Promise.prototype)
+var extensions = Object.create(Promise.prototype);
-extensions.status = function (expected) {
- var self_data = this[sym]
+extensions.status = function(expected) {
+ let self_data = this[sym];
- return extend(this, this.then(function (body) {
+ return extend(this, this.then(function(body) {
try {
- assert.equal(self_data.response.statusCode, expected)
+ assert.equal(self_data.response.statusCode, expected);
} catch(err) {
- self_data.error.message = err.message
- throw self_data.error
+ self_data.error.message = err.message;
+ throw self_data.error;
}
- return body
- }))
-}
+ return body;
+ }));
+};
-extensions.body_ok = function (expected) {
- var self_data = this[sym]
+extensions.body_ok = function(expected) {
+ let self_data = this[sym];
- return extend(this, this.then(function (body) {
+ return extend(this, this.then(function(body) {
try {
if (Object.prototype.toString.call(expected) === '[object RegExp]') {
- assert(body.ok.match(expected), "'" + body.ok + "' doesn't match " + expected)
+ assert(body.ok.match(expected), '\'' + body.ok + '\' doesn\'t match ' + expected);
} else {
- assert.equal(body.ok, expected)
+ assert.equal(body.ok, expected);
}
- assert.equal(body.error, null)
+ assert.equal(body.error, null);
} catch(err) {
- self_data.error.message = err.message
- throw self_data.error
+ self_data.error.message = err.message;
+ throw self_data.error;
}
- return body
- }))
-}
+ return body;
+ }));
+};
-extensions.body_error = function (expected) {
- var self_data = this[sym]
+extensions.body_error = function(expected) {
+ let self_data = this[sym];
- return extend(this, this.then(function (body) {
+ return extend(this, this.then(function(body) {
try {
if (Object.prototype.toString.call(expected) === '[object RegExp]') {
- assert(body.error.match(expected), body.error + " doesn't match " + expected)
+ assert(body.error.match(expected), body.error + ' doesn\'t match ' + expected);
} else {
- assert.equal(body.error, expected)
+ assert.equal(body.error, expected);
}
- assert.equal(body.ok, null)
+ assert.equal(body.ok, null);
} catch(err) {
- self_data.error.message = err.message
- throw self_data.error
+ self_data.error.message = err.message;
+ throw self_data.error;
}
- return body
- }))
-}
+ return body;
+ }));
+};
-extensions.request = function (cb) {
- cb(this[sym].request)
- return this
-}
+extensions.request = function(cb) {
+ cb(this[sym].request);
+ return this;
+};
-extensions.response = function (cb) {
- var self_data = this[sym]
+extensions.response = function(cb) {
+ let self_data = this[sym];
- return extend(this, this.then(function (body) {
- cb(self_data.response)
- return body
- }))
-}
+ return extend(this, this.then(function(body) {
+ cb(self_data.response);
+ return body;
+ }));
+};
-extensions.send = function (data) {
- this[sym].request.end(data)
- return this
-}
+extensions.send = function(data) {
+ this[sym].request.end(data);
+ return this;
+};
-module.exports = smart_request
+module.exports = smart_request;
diff --git a/test/functional/lib/startup.js b/test/functional/lib/startup.js
index 7e250d955..27e04c2ac 100644
--- a/test/functional/lib/startup.js
+++ b/test/functional/lib/startup.js
@@ -1,40 +1,44 @@
-var fork = require('child_process').fork
-var express = require('express')
-var rimraf = require('rimraf')
-var Server = require('./server')
+'use strict';
-var forks = process.forks = []
-process.server = Server('http://localhost:55551/')
-process.server2 = Server('http://localhost:55552/')
-process.express = express()
-process.express.listen(55550)
+const fork = require('child_process').fork;
+const express = require('express');
+const rimraf = require('rimraf');
+const Server = require('./server');
-module.exports.start = function start(dir, conf, cb) {
- rimraf(__dirname + '/../' + dir, function() {
- // filter out --debug-brk
- var oldArgv = process.execArgv
- process.execArgv = process.execArgv.filter(function(x) {
- return x !== '--debug-brk'
- })
+const forks = process.forks = [];
+process.server = Server('http://localhost:55551/');
+process.server2 = Server('http://localhost:55552/');
+process.express = express();
+process.express.listen(55550);
- var f = fork(__dirname + '/../../../bin/verdaccio'
- , ['-c', __dirname + '/../' + conf]
- , {silent: !process.env.TRAVIS}
- )
- forks.push(f)
- f.on('message', function(msg) {
- if ('verdaccio_started' in msg) {
- cb(), cb = function(){}
- }
- })
- f.on('error', function(err) {
- throw err
- })
- process.execArgv = oldArgv
- })
-}
+module.exports.start = function(dir, conf) {
+ return new Promise(function(resolve, reject) {
+ rimraf(__dirname + '/../' + dir, function() {
+ // filter out --debug-brk
+ let oldArgv = process.execArgv;
+ process.execArgv = process.execArgv.filter(function(x) {
+ return x !== '--debug-brk';
+ });
+
+ const f = fork(__dirname + '/../../../bin/verdaccio'
+ , ['-c', __dirname + '/../' + conf]
+ , {silent: !process.env.TRAVIS}
+ );
+ forks.push(f);
+ f.on('message', function(msg) {
+ if ('verdaccio_started' in msg) {
+ resolve();
+ }
+ });
+ f.on('error', function(err) {
+ reject(err);
+ });
+ process.execArgv = oldArgv;
+ });
+ });
+};
process.on('exit', function() {
- if (forks[0]) forks[0].kill()
- if (forks[1]) forks[1].kill()
-})
+ if (forks[0]) forks[0].kill();
+ if (forks[1]) forks[1].kill();
+});
diff --git a/test/functional/logout.js b/test/functional/logout.js
index 3729e70c9..8bc5858f4 100644
--- a/test/functional/logout.js
+++ b/test/functional/logout.js
@@ -1,11 +1,13 @@
+'use strict';
+
module.exports = function() {
- var server = process.server
+ let server = process.server;
describe('logout', function() {
- it('should log out', function () {
+ it('should log out', function() {
return server.logout('some-token')
.status(200)
- .body_ok(/Logged out/)
- })
- })
-}
+ .body_ok(/Logged out/);
+ });
+ });
+};
diff --git a/test/functional/mirror.js b/test/functional/mirror.js
index d1105ca1c..4b7662a4e 100644
--- a/test/functional/mirror.js
+++ b/test/functional/mirror.js
@@ -1,64 +1,66 @@
-var assert = require('assert')
+'use strict';
+
+let assert = require('assert');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
module.exports = function() {
- var server = process.server
- var server2 = process.server2
+ let server = process.server;
+ let server2 = process.server2;
- it('testing anti-loop', function () {
+ it('testing anti-loop', function() {
return server2.get_package('testloop')
.status(404)
- .body_error(/no such package/)
+ .body_error(/no such package/);
})
- ;['fwd', /*'loop'*/].forEach(function(pkg) {
- var prefix = pkg + ': '
- pkg = 'test' + pkg
+ ;['fwd'].forEach(function(pkg) {
+ let prefix = pkg + ': ';
+ pkg = 'test' + pkg;
describe(pkg, function() {
- before(function () {
+ before(function() {
return server.put_package(pkg, require('./lib/package')(pkg))
.status(201)
- .body_ok(/created new package/)
- })
+ .body_ok(/created new package/);
+ });
- it(prefix+'creating new package', function(){})
+ it(prefix+'creating new package', function() {});
describe(pkg, function() {
- before(function () {
+ before(function() {
return server.put_version(pkg, '0.1.1', require('./lib/package')(pkg))
.status(201)
- .body_ok(/published/)
- })
+ .body_ok(/published/);
+ });
- it(prefix+'uploading new package version', function(){})
+ it(prefix+'uploading new package version', function() {});
- it(prefix+'uploading incomplete tarball', function () {
- return server.put_tarball_incomplete(pkg, pkg+'.bad', readfile('fixtures/binary'), 3000)
- })
+ it(prefix+'uploading incomplete tarball', function() {
+ return server.put_tarball_incomplete(pkg, pkg+'.bad', readfile('fixtures/binary'), 3000);
+ });
describe('tarball', function() {
- before(function () {
+ before(function() {
return server.put_tarball(pkg, pkg+'.file', readfile('fixtures/binary'))
.status(201)
- .body_ok(/.*/)
- })
+ .body_ok(/.*/);
+ });
- it(prefix+'uploading new tarball', function(){})
+ it(prefix+'uploading new tarball', function() {});
- it(prefix+'downloading tarball from server1', function () {
+ it(prefix+'downloading tarball from server1', function() {
return server.get_tarball(pkg, pkg+'.file')
.status(200)
- .then(function (body) {
- assert.deepEqual(body, readfile('fixtures/binary'))
- })
- })
- })
- })
- })
- })
-}
+ .then(function(body) {
+ assert.deepEqual(body, readfile('fixtures/binary'));
+ });
+ });
+ });
+ });
+ });
+ });
+};
diff --git a/test/functional/newnpmreg.js b/test/functional/newnpmreg.js
index ee9311420..03b751225 100644
--- a/test/functional/newnpmreg.js
+++ b/test/functional/newnpmreg.js
@@ -1,20 +1,22 @@
-var assert = require('assert')
+'use strict';
+
+let assert = require('assert');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
function sha(x) {
- return require('crypto').createHash('sha1', 'binary').update(x).digest('hex')
+ return require('crypto').createHash('sha1', 'binary').update(x).digest('hex');
}
module.exports = function() {
- var server = process.server
- var server2 = process.server2
- var express = process.express
+ let server = process.server;
+ let server2 = process.server2;
+ let express = process.express;
describe('newnpmreg', function() {
- before(function () {
+ before(function() {
return server.request({
uri: '/testpkg-newnpmreg',
headers: {
@@ -22,100 +24,100 @@ module.exports = function() {
},
method: 'PUT',
json: JSON.parse(readfile('fixtures/newnpmreg.json')),
- }).status(201)
- })
+ }).status(201);
+ });
- it('add pkg', function () {})
+ it('add pkg', function() {});
- it('server1 - tarball', function () {
+ it('server1 - tarball', function() {
return server.get_tarball('testpkg-newnpmreg', 'testpkg-newnpmreg-0.0.0.tgz')
.status(200)
- .then(function (body) {
+ .then(function(body) {
// not real sha due to utf8 conversion
- assert.strictEqual(sha(body), '8ee7331cbc641581b1a8cecd9d38d744a8feb863')
- })
- })
+ assert.strictEqual(sha(body), '8ee7331cbc641581b1a8cecd9d38d744a8feb863');
+ });
+ });
- it('server2 - tarball', function () {
+ it('server2 - tarball', function() {
return server2.get_tarball('testpkg-newnpmreg', 'testpkg-newnpmreg-0.0.0.tgz')
.status(200)
- .then(function (body) {
+ .then(function(body) {
// not real sha due to utf8 conversion
- assert.strictEqual(sha(body), '8ee7331cbc641581b1a8cecd9d38d744a8feb863')
- })
- })
+ assert.strictEqual(sha(body), '8ee7331cbc641581b1a8cecd9d38d744a8feb863');
+ });
+ });
- it('server1 - package', function () {
+ it('server1 - package', function() {
return server.get_package('testpkg-newnpmreg')
.status(200)
- .then(function (body) {
- assert.equal(body.name, 'testpkg-newnpmreg')
- assert.equal(body.versions['0.0.0'].name, 'testpkg-newnpmreg')
- assert.equal(body.versions['0.0.0'].dist.tarball, 'http://localhost:55551/testpkg-newnpmreg/-/testpkg-newnpmreg-0.0.0.tgz')
- assert.deepEqual(body['dist-tags'], {foo: '0.0.0', latest: '0.0.0'})
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, 'testpkg-newnpmreg');
+ assert.equal(body.versions['0.0.0'].name, 'testpkg-newnpmreg');
+ assert.equal(body.versions['0.0.0'].dist.tarball, 'http://localhost:55551/testpkg-newnpmreg/-/testpkg-newnpmreg-0.0.0.tgz');
+ assert.deepEqual(body['dist-tags'], {foo: '0.0.0', latest: '0.0.0'});
+ });
+ });
- it('server2 - package', function () {
+ it('server2 - package', function() {
return server2.get_package('testpkg-newnpmreg')
.status(200)
- .then(function (body) {
- assert.equal(body.name, 'testpkg-newnpmreg')
- assert.equal(body.versions['0.0.0'].name, 'testpkg-newnpmreg')
- assert.equal(body.versions['0.0.0'].dist.tarball, 'http://localhost:55552/testpkg-newnpmreg/-/testpkg-newnpmreg-0.0.0.tgz')
- assert.deepEqual(body['dist-tags'], {foo: '0.0.0', latest: '0.0.0'})
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, 'testpkg-newnpmreg');
+ assert.equal(body.versions['0.0.0'].name, 'testpkg-newnpmreg');
+ assert.equal(body.versions['0.0.0'].dist.tarball, 'http://localhost:55552/testpkg-newnpmreg/-/testpkg-newnpmreg-0.0.0.tgz');
+ assert.deepEqual(body['dist-tags'], {foo: '0.0.0', latest: '0.0.0'});
+ });
+ });
- it('server1 - readme', function () {
- return server.request({ uri: '/-/readme/testpkg-newnpmreg' })
+ it('server1 - readme', function() {
+ return server.request({uri: '/-/readme/testpkg-newnpmreg'})
.status(200)
- .then(function (body) {
- assert.equal(body, 'blah blah blah
\n')
- })
- })
+ .then(function(body) {
+ assert.equal(body, 'blah blah blah
\n');
+ });
+ });
- it('server2 - readme', function () {
- return server2.request({ uri: '/-/readme/testpkg-newnpmreg' })
+ it('server2 - readme', function() {
+ return server2.request({uri: '/-/readme/testpkg-newnpmreg'})
.status(200)
- .then(function (body) {
- assert.equal(body, 'blah blah blah
\n')
- })
- })
+ .then(function(body) {
+ assert.equal(body, 'blah blah blah
\n');
+ });
+ });
describe('search', function() {
function check(obj) {
- obj['testpkg-newnpmreg'].time.modified = '2014-10-02T07:07:51.000Z'
+ obj['testpkg-newnpmreg'].time.modified = '2014-10-02T07:07:51.000Z';
assert.deepEqual(obj['testpkg-newnpmreg'],
- { name: 'testpkg-newnpmreg',
- description: '',
- author: '',
- license: 'ISC',
- 'dist-tags': { latest: '0.0.0' },
- maintainers: [ { name: 'alex', email: 'alex@kocharin.ru' } ],
- readmeFilename: '',
- time: { modified: '2014-10-02T07:07:51.000Z' },
- versions: {},
- repository: { type: 'git', url: '' } })
+ {'name': 'testpkg-newnpmreg',
+ 'description': '',
+ 'author': '',
+ 'license': 'ISC',
+ 'dist-tags': {latest: '0.0.0'},
+ 'maintainers': [{name: 'alex', email: 'alex@kocharin.ru'}],
+ 'readmeFilename': '',
+ 'time': {modified: '2014-10-02T07:07:51.000Z'},
+ 'versions': {},
+ 'repository': {type: 'git', url: ''}});
}
- before(function () {
+ before(function() {
express.get('/-/all', function(req, res) {
- res.send({})
- })
- })
+ res.send({});
+ });
+ });
- it('server1 - search', function () {
- return server.request({ uri: '/-/all' })
+ it('server1 - search', function() {
+ return server.request({uri: '/-/all'})
.status(200)
- .then(check)
- })
+ .then(check);
+ });
- it('server2 - search', function () {
- return server2.request({ uri: '/-/all' })
+ it('server2 - search', function() {
+ return server2.request({uri: '/-/all'})
.status(200)
- .then(check)
- })
- })
- })
-}
+ .then(check);
+ });
+ });
+ });
+};
diff --git a/test/functional/nullstorage.js b/test/functional/nullstorage.js
index 11857a422..bdf714d8b 100644
--- a/test/functional/nullstorage.js
+++ b/test/functional/nullstorage.js
@@ -1,71 +1,73 @@
-require('./lib/startup')
+'use strict';
-var assert = require('assert')
-var crypto = require('crypto')
+require('./lib/startup');
+
+let assert = require('assert');
+let crypto = require('crypto');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
module.exports = function() {
- var server = process.server
- var server2 = process.server2
+ let server = process.server;
+ let server2 = process.server2;
- it('trying to fetch non-existent package / null storage', function () {
+ it('trying to fetch non-existent package / null storage', function() {
return server.get_package('test-nullstorage-nonexist')
.status(404)
- .body_error(/no such package/)
- })
+ .body_error(/no such package/);
+ });
describe('test-nullstorage on server2', function() {
- before(function () {
- return server2.add_package('test-nullstorage2')
- })
+ before(function() {
+ return server2.add_package('test-nullstorage2');
+ });
- it('creating new package - server2', function(){/* test for before() */})
+ it('creating new package - server2', function() {/* test for before() */});
- it('downloading non-existent tarball', function () {
+ it('downloading non-existent tarball', function() {
return server.get_tarball('test-nullstorage2', 'blahblah')
.status(404)
- .body_error(/no such file/)
- })
+ .body_error(/no such file/);
+ });
describe('tarball', function() {
- before(function () {
+ before(function() {
return server2.put_tarball('test-nullstorage2', 'blahblah', readfile('fixtures/binary'))
.status(201)
- .body_ok(/.*/)
- })
+ .body_ok(/.*/);
+ });
- before(function () {
- var pkg = require('./lib/package')('test-nullstorage2')
- pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex')
+ before(function() {
+ let pkg = require('./lib/package')('test-nullstorage2');
+ pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server2.put_version('test-nullstorage2', '0.0.1', pkg)
.status(201)
- .body_ok(/published/)
- })
+ .body_ok(/published/);
+ });
- it('uploading new tarball', function () {/* test for before() */})
+ it('uploading new tarball', function() {/* test for before() */});
- it('downloading newly created tarball', function () {
+ it('downloading newly created tarball', function() {
return server.get_tarball('test-nullstorage2', 'blahblah')
.status(200)
- .then(function (body) {
- assert.deepEqual(body, readfile('fixtures/binary'))
- })
- })
+ .then(function(body) {
+ assert.deepEqual(body, readfile('fixtures/binary'));
+ });
+ });
- it('downloading newly created package', function () {
+ it('downloading newly created package', function() {
return server.get_package('test-nullstorage2')
.status(200)
- .then(function (body) {
- assert.equal(body.name, 'test-nullstorage2')
- assert.equal(body.versions['0.0.1'].name, 'test-nullstorage2')
- assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/test-nullstorage2/-/blahblah')
- assert.deepEqual(body['dist-tags'], {latest: '0.0.1'})
- })
- })
- })
- })
-}
+ .then(function(body) {
+ assert.equal(body.name, 'test-nullstorage2');
+ assert.equal(body.versions['0.0.1'].name, 'test-nullstorage2');
+ assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/test-nullstorage2/-/blahblah');
+ assert.deepEqual(body['dist-tags'], {latest: '0.0.1'});
+ });
+ });
+ });
+ });
+};
diff --git a/test/functional/plugins.js b/test/functional/plugins.js
index 5b22d5170..803ae0f22 100644
--- a/test/functional/plugins.js
+++ b/test/functional/plugins.js
@@ -1,120 +1,122 @@
-require('./lib/startup')
+'use strict';
-var assert = require('assert')
+require('./lib/startup');
+
+let assert = require('assert');
module.exports = function() {
- var server2 = process.server2
+ let server2 = process.server2;
describe('authentication', function() {
- var authstr
+ let authstr;
before(function() {
- authstr = server2.authstr
- })
+ authstr = server2.authstr;
+ });
- it('should not authenticate with wrong password', function () {
+ it('should not authenticate with wrong password', function() {
return server2.auth('authtest', 'wrongpass')
.status(409)
.body_error('this user already exists')
- .then(function () {
- return server2.whoami()
+ .then(function() {
+ return server2.whoami();
})
- .then(function (username) {
- assert.equal(username, null)
- })
- })
+ .then(function(username) {
+ assert.equal(username, null);
+ });
+ });
- it('wrong password handled by plugin', function () {
+ it('wrong password handled by plugin', function() {
return server2.auth('authtest2', 'wrongpass')
.status(409)
.body_error('registration is disabled')
- .then(function () {
- return server2.whoami()
+ .then(function() {
+ return server2.whoami();
})
- .then(function (username) {
- assert.equal(username, null)
- })
- })
+ .then(function(username) {
+ assert.equal(username, null);
+ });
+ });
- it('right password handled by plugin', function () {
+ it('right password handled by plugin', function() {
return server2.auth('authtest2', 'blahblah')
.status(201)
.body_ok(/'authtest2'/)
- .then(function () {
- return server2.whoami()
+ .then(function() {
+ return server2.whoami();
})
- .then(function (username) {
- assert.equal(username, 'authtest2')
- })
- })
+ .then(function(username) {
+ assert.equal(username, 'authtest2');
+ });
+ });
after(function() {
- server2.authstr = authstr
- })
- })
+ server2.authstr = authstr;
+ });
+ });
describe('authorization', function() {
- var authstr
+ let authstr;
before(function() {
- authstr = server2.authstr
- })
+ authstr = server2.authstr;
+ });
describe('authtest', function() {
- before(function () {
+ before(function() {
return server2.auth('authtest', 'test')
.status(201)
- .body_ok(/'authtest'/)
- })
+ .body_ok(/'authtest'/);
+ });
- it('access test-auth-allow', function () {
+ it('access test-auth-allow', function() {
return server2.get_package('test-auth-allow')
.status(404)
- .body_error('no such package available')
- })
+ .body_error('no such package available');
+ });
- it('access test-auth-deny', function () {
+ it('access test-auth-deny', function() {
return server2.get_package('test-auth-deny')
.status(403)
- .body_error("you're not allowed here")
- })
+ .body_error('you\'re not allowed here');
+ });
- it('access test-auth-regular', function () {
+ it('access test-auth-regular', function() {
return server2.get_package('test-auth-regular')
.status(404)
- .body_error('no such package available')
- })
- })
+ .body_error('no such package available');
+ });
+ });
describe('authtest2', function() {
- before(function () {
+ before(function() {
return server2.auth('authtest2', 'blahblah')
.status(201)
- .body_ok(/'authtest2'/)
- })
+ .body_ok(/'authtest2'/);
+ });
- it('access test-auth-allow', function () {
+ it('access test-auth-allow', function() {
return server2.get_package('test-auth-allow')
.status(403)
- .body_error("i don't know anything about you")
- })
+ .body_error('i don\'t know anything about you');
+ });
- it('access test-auth-deny', function () {
+ it('access test-auth-deny', function() {
return server2.get_package('test-auth-deny')
.status(403)
- .body_error("i don't know anything about you")
- })
+ .body_error('i don\'t know anything about you');
+ });
- it('access test-auth-regular', function () {
+ it('access test-auth-regular', function() {
return server2.get_package('test-auth-regular')
.status(404)
- .body_error('no such package available')
- })
- })
+ .body_error('no such package available');
+ });
+ });
after(function() {
- server2.authstr = authstr
- })
- })
-}
+ server2.authstr = authstr;
+ });
+ });
+};
diff --git a/test/functional/plugins/authenticate.js b/test/functional/plugins/authenticate.js
index 2c4d68c69..6b638abe3 100644
--- a/test/functional/plugins/authenticate.js
+++ b/test/functional/plugins/authenticate.js
@@ -1,25 +1,26 @@
+'use strict';
-module.exports = Plugin
+module.exports = Plugin;
function Plugin(config, stuff) {
- var self = Object.create(Plugin.prototype)
- self._config = config
- return self
+ let self = Object.create(Plugin.prototype);
+ self._config = config;
+ return self;
}
// plugin is expected to be compatible with...
-Plugin.prototype.verdaccio_version = '1.1.0'
+Plugin.prototype.verdaccio_version = '1.1.0';
Plugin.prototype.authenticate = function(user, password, cb) {
- var self = this
+ let self = this;
if (user !== self._config.accept_user) {
// delegate to next plugin
- return cb(null, false)
+ return cb(null, false);
}
if (password !== self._config.with_password) {
- var err = Error("i don't like your password")
- err.status = 403
- return cb(err)
+ let err = Error('i don\'t like your password');
+ err.status = 403;
+ return cb(err);
}
- return cb(null, [ user ])
-}
+ return cb(null, [user]);
+};
diff --git a/test/functional/plugins/authorize.js b/test/functional/plugins/authorize.js
index 5c2a73227..50aac4f7c 100644
--- a/test/functional/plugins/authorize.js
+++ b/test/functional/plugins/authorize.js
@@ -1,30 +1,31 @@
+'use strict';
-module.exports = Plugin
+module.exports = Plugin;
function Plugin(config, stuff) {
- var self = Object.create(Plugin.prototype)
- self._config = config
- return self
+ let self = Object.create(Plugin.prototype);
+ self._config = config;
+ return self;
}
// plugin is expected to be compatible with...
-Plugin.prototype.verdaccio_version = '1.1.0'
+Plugin.prototype.verdaccio_version = '1.1.0';
-Plugin.prototype.allow_access = function(user, package, cb) {
- var self = this
- if (!package.handled_by_auth_plugin) {
+Plugin.prototype.allow_access = function(user, pkg, cb) {
+ let self = this;
+ if (!pkg.handled_by_auth_plugin) {
// delegate to next plugin
- return cb(null, false)
+ return cb(null, false);
}
if (user.name !== self._config.allow_user) {
- var err = Error("i don't know anything about you")
- err.status = 403
- return cb(err)
+ let err = Error('i don\'t know anything about you');
+ err.status = 403;
+ return cb(err);
}
- if (package.name !== self._config.to_access) {
- var err = Error("you're not allowed here")
- err.status = 403
- return cb(err)
+ if (pkg.name !== self._config.to_access) {
+ let err = Error('you\'re not allowed here');
+ err.status = 403;
+ return cb(err);
}
- return cb(null, true)
-}
+ return cb(null, true);
+};
diff --git a/test/functional/race.js b/test/functional/race.js
index 97aab5703..a619b8000 100644
--- a/test/functional/race.js
+++ b/test/functional/race.js
@@ -1,99 +1,105 @@
-var assert = require('assert')
-var async = require('async')
-var _oksum = 0
+'use strict';
+
+let assert = require('assert');
+let async = require('async');
+let _oksum = 0;
module.exports = function() {
- var server = process.server
+ let server = process.server;
describe('race', function() {
- before(function () {
+ before(function() {
return server.put_package('race', require('./lib/package')('race'))
.status(201)
- .body_ok(/created new package/)
- })
+ .body_ok(/created new package/);
+ });
- it('creating new package', function(){})
+ it('creating new package', function() {});
- it('uploading 10 same versions', function (callback) {
- var fns = []
- for (var i=0; i<10; i++) {
+ it('uploading 10 same versions', function(callback) {
+ let fns = [];
+ for (let i=0; i<10; i++) {
fns.push(function(cb_) {
- var data = require('./lib/package')('race')
- data.rand = Math.random()
+ let data = require('./lib/package')('race');
+ data.rand = Math.random();
- var _res
+ let _res;
server.put_version('race', '0.0.1', data)
- .response(function (res) { _res = res })
- .then(function (body) {
- cb_(null, [ _res, body ])
- })
- })
+ .response(function(res) {
+ _res = res;
+})
+ .then(function(body) {
+ cb_(null, [_res, body]);
+ });
+ });
}
async.parallel(fns, function(err, res) {
- var okcount = 0
- var failcount = 0
+ let okcount = 0;
+ let failcount = 0;
- assert.equal(err, null)
+ assert.equal(err, null);
res.forEach(function(arr) {
- var resp = arr[0]
- var body = arr[1]
+ let resp = arr[0];
+ let body = arr[1];
- if (resp.statusCode === 201 && ~body.ok.indexOf('published')) okcount++
- if (resp.statusCode === 409 && ~body.error.indexOf('already present')) failcount++
- if (resp.statusCode === 503 && ~body.error.indexOf('unavailable')) failcount++
- })
- assert.equal(okcount + failcount, 10)
- assert.equal(okcount, 1)
- _oksum += okcount
+ if (resp.statusCode === 201 && ~body.ok.indexOf('published')) okcount++;
+ if (resp.statusCode === 409 && ~body.error.indexOf('already present')) failcount++;
+ if (resp.statusCode === 503 && ~body.error.indexOf('unavailable')) failcount++;
+ });
+ assert.equal(okcount + failcount, 10);
+ assert.equal(okcount, 1);
+ _oksum += okcount;
- callback()
- })
- })
+ callback();
+ });
+ });
- it('uploading 10 diff versions', function (callback) {
- var fns = []
- for (var i=0; i<10; i++) {
- ;(function(i) {
+ it('uploading 10 diff versions', function(callback) {
+ let fns = [];
+ for (let i=0; i<10; i++) {
+ (function(i) {
fns.push(function(cb_) {
- var _res
+ let _res;
server.put_version('race', '0.1.'+String(i), require('./lib/package')('race'))
- .response(function (res) { _res = res })
- .then(function (body) {
- cb_(null, [ _res, body ])
- })
- })
- })(i)
+ .response(function(res) {
+ _res = res;
+})
+ .then(function(body) {
+ cb_(null, [_res, body]);
+ });
+ });
+ })(i);
}
async.parallel(fns, function(err, res) {
- var okcount = 0
- var failcount = 0
+ let okcount = 0;
+ let failcount = 0;
- assert.equal(err, null)
+ assert.equal(err, null);
res.forEach(function(arr) {
- var resp = arr[0]
- var body = arr[1]
- if (resp.statusCode === 201 && ~body.ok.indexOf('published')) okcount++
- if (resp.statusCode === 409 && ~body.error.indexOf('already present')) failcount++
- if (resp.statusCode === 503 && ~body.error.indexOf('unavailable')) failcount++
- })
- assert.equal(okcount + failcount, 10)
- assert.notEqual(okcount, 1)
- _oksum += okcount
+ let resp = arr[0];
+ let body = arr[1];
+ if (resp.statusCode === 201 && ~body.ok.indexOf('published')) okcount++;
+ if (resp.statusCode === 409 && ~body.error.indexOf('already present')) failcount++;
+ if (resp.statusCode === 503 && ~body.error.indexOf('unavailable')) failcount++;
+ });
+ assert.equal(okcount + failcount, 10);
+ assert.notEqual(okcount, 1);
+ _oksum += okcount;
- callback()
- })
- })
+ callback();
+ });
+ });
- after('downloading package', function () {
+ after('downloading package', function() {
return server.get_package('race')
.status(200)
- .then(function (body) {
- assert.equal(Object.keys(body.versions).length, _oksum)
- })
- })
- })
-}
+ .then(function(body) {
+ assert.equal(Object.keys(body.versions).length, _oksum);
+ });
+ });
+ });
+};
diff --git a/test/functional/racycrash.js b/test/functional/racycrash.js
index de5e5c21d..7e57082ea 100644
--- a/test/functional/racycrash.js
+++ b/test/functional/racycrash.js
@@ -1,66 +1,70 @@
-var assert = require('assert')
+'use strict';
+
+let assert = require('assert');
module.exports = function() {
- var server = process.server
- var express = process.express
+ let server = process.server;
+ let express = process.express;
describe('Racy', function() {
- var on_tarball
+ let on_tarball;
before(function() {
express.get('/testexp-racycrash', function(_, res) {
res.send({
- "name": "testexp-racycrash",
- "versions": {
- "0.1.0": {
- "name": "testexp_tags",
- "version": "0.1.0",
- "dist": {
- "shasum": "fake",
- "tarball": "http://localhost:55550/testexp-racycrash/-/test.tar.gz"
- }
- }
- }
- })
- })
+ 'name': 'testexp-racycrash',
+ 'versions': {
+ '0.1.0': {
+ 'name': 'testexp_tags',
+ 'version': '0.1.0',
+ 'dist': {
+ 'shasum': 'fake',
+ 'tarball': 'http://localhost:55550/testexp-racycrash/-/test.tar.gz',
+ },
+ },
+ },
+ });
+ });
express.get('/testexp-racycrash/-/test.tar.gz', function(_, res) {
- on_tarball(res)
- })
- })
+ on_tarball(res);
+ });
+ });
it('should not crash on error if client disconnects', function(_cb) {
on_tarball = function(res) {
- res.header('content-length', 1e6)
- res.write('test test test\n')
+ res.header('content-length', 1e6);
+ res.write('test test test\n');
setTimeout(function() {
- res.write('test test test\n')
- res.socket.destroy()
- cb()
- }, 200)
- }
+ res.write('test test test\n');
+ res.socket.destroy();
+ cb();
+ }, 200);
+ };
- server.request({ uri: '/testexp-racycrash/-/test.tar.gz' })
- .then(function (body) {
- assert.equal(body, 'test test test\n')
- })
+ server.request({uri: '/testexp-racycrash/-/test.tar.gz'})
+ .then(function(body) {
+ assert.equal(body, 'test test test\n');
+ });
function cb() {
// test for NOT crashing
- server.request({ uri: '/testexp-racycrash' })
+ server.request({uri: '/testexp-racycrash'})
.status(200)
- .then(function () { _cb() })
+ .then(function() {
+ _cb();
+});
}
- })
+ });
- it('should not store tarball', function () {
+ it('should not store tarball', function() {
on_tarball = function(res) {
- res.socket.destroy()
- }
+ res.socket.destroy();
+ };
- return server.request({ uri: '/testexp-racycrash/-/test.tar.gz' })
- .body_error('internal server error')
- })
- })
-}
+ return server.request({uri: '/testexp-racycrash/-/test.tar.gz'})
+ .body_error('internal server error');
+ });
+ });
+};
diff --git a/test/functional/scoped.js b/test/functional/scoped.js
index f25f16260..ed06df644 100644
--- a/test/functional/scoped.js
+++ b/test/functional/scoped.js
@@ -1,19 +1,21 @@
-var assert = require('assert')
+'use strict';
+
+let assert = require('assert');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
function sha(x) {
- return require('crypto').createHash('sha1', 'binary').update(x).digest('hex')
+ return require('crypto').createHash('sha1', 'binary').update(x).digest('hex');
}
module.exports = function() {
- var server = process.server
- var server2 = process.server2
+ let server = process.server;
+ let server2 = process.server2;
describe('test-scoped', function() {
- before(function () {
+ before(function() {
return server.request({
uri: '/@test%2fscoped',
headers: {
@@ -21,58 +23,58 @@ module.exports = function() {
},
method: 'PUT',
json: JSON.parse(readfile('fixtures/scoped.json')),
- }).status(201)
- })
+ }).status(201);
+ });
- it('add pkg', function () {})
+ it('add pkg', function() {});
- it('server1 - tarball', function () {
+ it('server1 - tarball', function() {
return server.get_tarball('@test/scoped', 'scoped-1.0.0.tgz')
.status(200)
- .then(function (body) {
+ .then(function(body) {
// not real sha due to utf8 conversion
- assert.strictEqual(sha(body), '6e67b14e2c0e450b942e2bc8086b49e90f594790')
- })
- })
+ assert.strictEqual(sha(body), '6e67b14e2c0e450b942e2bc8086b49e90f594790');
+ });
+ });
- it('server2 - tarball', function () {
+ it('server2 - tarball', function() {
return server2.get_tarball('@test/scoped', 'scoped-1.0.0.tgz')
.status(200)
- .then(function (body) {
+ .then(function(body) {
// not real sha due to utf8 conversion
- assert.strictEqual(sha(body), '6e67b14e2c0e450b942e2bc8086b49e90f594790')
- })
- })
+ assert.strictEqual(sha(body), '6e67b14e2c0e450b942e2bc8086b49e90f594790');
+ });
+ });
- it('server1 - package', function () {
+ it('server1 - package', function() {
return server.get_package('@test/scoped')
.status(200)
- .then(function (body) {
- assert.equal(body.name, '@test/scoped')
- assert.equal(body.versions['1.0.0'].name, '@test/scoped')
- assert.equal(body.versions['1.0.0'].dist.tarball, 'http://localhost:55551/@test%2fscoped/-/scoped-1.0.0.tgz')
- assert.deepEqual(body['dist-tags'], {latest: '1.0.0'})
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, '@test/scoped');
+ assert.equal(body.versions['1.0.0'].name, '@test/scoped');
+ assert.equal(body.versions['1.0.0'].dist.tarball, 'http://localhost:55551/@test%2fscoped/-/scoped-1.0.0.tgz');
+ assert.deepEqual(body['dist-tags'], {latest: '1.0.0'});
+ });
+ });
- it('server2 - package', function () {
+ it('server2 - package', function() {
return server2.get_package('@test/scoped')
.status(200)
- .then(function (body) {
- assert.equal(body.name, '@test/scoped')
- assert.equal(body.versions['1.0.0'].name, '@test/scoped')
- assert.equal(body.versions['1.0.0'].dist.tarball, 'http://localhost:55552/@test%2fscoped/-/scoped-1.0.0.tgz')
- assert.deepEqual(body['dist-tags'], {latest: '1.0.0'})
- })
- })
+ .then(function(body) {
+ assert.equal(body.name, '@test/scoped');
+ assert.equal(body.versions['1.0.0'].name, '@test/scoped');
+ assert.equal(body.versions['1.0.0'].dist.tarball, 'http://localhost:55552/@test%2fscoped/-/scoped-1.0.0.tgz');
+ assert.deepEqual(body['dist-tags'], {latest: '1.0.0'});
+ });
+ });
- it('server2 - nginx workaround', function () {
- return server2.request({ uri: '/@test/scoped/1.0.0' })
+ it('server2 - nginx workaround', function() {
+ return server2.request({uri: '/@test/scoped/1.0.0'})
.status(200)
- .then(function (body) {
- assert.equal(body.name, '@test/scoped')
- assert.equal(body.dist.tarball, 'http://localhost:55552/@test%2fscoped/-/scoped-1.0.0.tgz')
- })
- })
- })
-}
+ .then(function(body) {
+ assert.equal(body.name, '@test/scoped');
+ assert.equal(body.dist.tarball, 'http://localhost:55552/@test%2fscoped/-/scoped-1.0.0.tgz');
+ });
+ });
+ });
+};
diff --git a/test/functional/security.js b/test/functional/security.js
index 961f56c16..51781ef37 100644
--- a/test/functional/security.js
+++ b/test/functional/security.js
@@ -1,70 +1,72 @@
-var assert = require('assert')
+'use strict';
+
+const assert = require('assert');
module.exports = function() {
- var server = process.server
+ let server = process.server;
describe('Security', function() {
before(function() {
- return server.add_package('testpkg-sec')
- })
+ return server.add_package('testpkg-sec');
+ });
- it('bad pkg #1', function () {
+ it('bad pkg #1', function() {
return server.get_package('package.json')
.status(403)
- .body_error(/invalid package/)
- })
+ .body_error(/invalid package/);
+ });
- it('bad pkg #2', function () {
+ it('bad pkg #2', function() {
return server.get_package('__proto__')
.status(403)
- .body_error(/invalid package/)
- })
+ .body_error(/invalid package/);
+ });
- it('__proto__, connect stuff', function () {
- return server.request({ uri: '/testpkg-sec?__proto__=1' })
- .then(function (body) {
+ it('__proto__, connect stuff', function() {
+ return server.request({uri: '/testpkg-sec?__proto__=1'})
+ .then(function(body) {
// test for NOT outputting stack trace
- assert(!body || typeof(body) === 'object' || body.indexOf('node_modules') === -1)
+ assert(!body || typeof(body) === 'object' || body.indexOf('node_modules') === -1);
// test for NOT crashing
- return server.request({ uri: '/testpkg-sec' }).status(200)
- })
- })
+ return server.request({uri: '/testpkg-sec'}).status(200);
+ });
+ });
- it('do not return package.json as an attachment', function () {
- return server.request({ uri: '/testpkg-sec/-/package.json' })
+ it('do not return package.json as an attachment', function() {
+ return server.request({uri: '/testpkg-sec/-/package.json'})
.status(403)
- .body_error(/invalid filename/)
- })
+ .body_error(/invalid filename/);
+ });
- it('silly things - reading #1', function () {
- return server.request({ uri: '/testpkg-sec/-/../../../../../../../../etc/passwd' })
- .status(404)
- })
+ it('silly things - reading #1', function() {
+ return server.request({uri: '/testpkg-sec/-/../../../../../../../../etc/passwd'})
+ .status(404);
+ });
- it('silly things - reading #2', function () {
- return server.request({ uri: '/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd' })
+ it('silly things - reading #2', function() {
+ return server.request({uri: '/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd'})
.status(403)
- .body_error(/invalid filename/)
- })
+ .body_error(/invalid filename/);
+ });
- it('silly things - writing #1', function () {
+ it('silly things - writing #1', function() {
return server.put_tarball('testpkg-sec', 'package.json', '{}')
.status(403)
- .body_error(/invalid filename/)
- })
+ .body_error(/invalid filename/);
+ });
- it('silly things - writing #3', function () {
+ it('silly things - writing #3', function() {
return server.put_tarball('testpkg-sec', 'node_modules', '{}')
.status(403)
- .body_error(/invalid filename/)
- })
+ .body_error(/invalid filename/);
+ });
- it('silly things - writing #4', function () {
+ it('silly things - writing #4', function() {
return server.put_tarball('testpkg-sec', '../testpkg.tgz', '{}')
.status(403)
- .body_error(/invalid filename/)
- })
- })
-}
+ .body_error(/invalid filename/);
+ });
+ });
+};
diff --git a/test/functional/tags.js b/test/functional/tags.js
index b90068bc6..ebc62c872 100644
--- a/test/functional/tags.js
+++ b/test/functional/tags.js
@@ -1,168 +1,170 @@
-var assert = require('assert')
+'use strict';
+
+const assert = require('assert');
function readfile(x) {
- return require('fs').readFileSync(__dirname + '/' + x)
+ return require('fs').readFileSync(__dirname + '/' + x);
}
module.exports = function() {
- var server = process.server
- var express = process.express
+ let server = process.server;
+ let express = process.express;
- it('tags - testing for 404', function () {
+ it('tags - testing for 404', function() {
return server.get_package('testexp_tags')
// shouldn't exist yet
.status(404)
- .body_error(/no such package/)
- })
+ .body_error(/no such package/);
+ });
describe('tags', function() {
- before(function () {
+ before(function() {
express.get('/testexp_tags', function(req, res) {
- var f = readfile('fixtures/tags.json').toString().replace(/__NAME__/g, 'testexp_tags')
- res.send(JSON.parse(f))
- })
- })
+ let f = readfile('fixtures/tags.json').toString().replace(/__NAME__/g, 'testexp_tags');
+ res.send(JSON.parse(f));
+ });
+ });
- it('fetching package again', function () {
+ it('fetching package again', function() {
return server.get_package('testexp_tags')
.status(200)
- .then(function (body) {
- assert.equal(typeof(body.versions['1.1']), 'object')
- assert.equal(body['dist-tags'].something, '0.1.1alpha')
+ .then(function(body) {
+ assert.equal(typeof(body.versions['1.1']), 'object');
+ assert.equal(body['dist-tags'].something, '0.1.1alpha');
// note: 5.4.3 is invalid tag, 0.1.3alpha is highest semver
- assert.equal(body['dist-tags'].latest, '0.1.3alpha')
- assert.equal(body['dist-tags'].bad, null)
- })
+ assert.equal(body['dist-tags'].latest, '0.1.3alpha');
+ assert.equal(body['dist-tags'].bad, null);
+ });
})
;['0.1.1alpha', '0.1.1-alpha', '0000.00001.001-alpha'].forEach(function(ver) {
- it('fetching '+ver, function () {
- return server.request({uri:'/testexp_tags/'+ver})
+ it('fetching '+ver, function() {
+ return server.request({uri: '/testexp_tags/'+ver})
.status(200)
- .then(function (body) {
- assert.equal(body.version, '0.1.1alpha')
- })
- })
- })
- })
+ .then(function(body) {
+ assert.equal(body.version, '0.1.1alpha');
+ });
+ });
+ });
+ });
describe('dist-tags methods', function() {
- before(function () {
+ before(function() {
express.get('/testexp_tags2', function(req, res) {
- var f = readfile('fixtures/tags.json').toString().replace(/__NAME__/g, 'testexp_tags2')
- res.send(JSON.parse(f))
- })
- })
+ let f = readfile('fixtures/tags.json').toString().replace(/__NAME__/g, 'testexp_tags2');
+ res.send(JSON.parse(f));
+ });
+ });
// populate cache
- before(function () {
+ before(function() {
return server.get_package('testexp_tags2')
- .status(200)
- })
+ .status(200);
+ });
- beforeEach(function () {
+ beforeEach(function() {
return server.request({
method: 'PUT',
- uri: '/-/package/testexp_tags2/dist-tags',
- json: {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ json: {
foo: '0.1.0',
bar: '0.1.1alpha',
baz: '0.1.2',
},
- }).status(201).body_ok(/tags updated/)
- })
+ }).status(201).body_ok(/tags updated/);
+ });
- it('fetching tags', function () {
+ it('fetching tags', function() {
return server.request({
method: 'GET',
- uri: '/-/package/testexp_tags2/dist-tags',
- }).status(200).then(function (body) {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ }).status(200).then(function(body) {
assert.deepEqual(body,
- { foo: '0.1.0',
+ {foo: '0.1.0',
bar: '0.1.1alpha',
baz: '0.1.2',
- latest: '0.1.3alpha' })
- })
- })
+ latest: '0.1.3alpha'});
+ });
+ });
- it('merging tags', function () {
+ it('merging tags', function() {
return server.request({
method: 'POST',
- uri: '/-/package/testexp_tags2/dist-tags',
- json: {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ json: {
foo: '0.1.2',
quux: '0.1.0',
},
- }).status(201).body_ok(/updated/).then(function () {
+ }).status(201).body_ok(/updated/).then(function() {
return server.request({
method: 'GET',
- uri: '/-/package/testexp_tags2/dist-tags',
- }).status(200).then(function (body) {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ }).status(200).then(function(body) {
assert.deepEqual(body,
- { foo: '0.1.2',
+ {foo: '0.1.2',
bar: '0.1.1alpha',
baz: '0.1.2',
quux: '0.1.0',
- latest: '0.1.3alpha' })
- })
- })
- })
+ latest: '0.1.3alpha'});
+ });
+ });
+ });
- it('replacing tags', function () {
+ it('replacing tags', function() {
return server.request({
method: 'PUT',
- uri: '/-/package/testexp_tags2/dist-tags',
- json: {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ json: {
foo: '0.1.2',
quux: '0.1.0',
},
- }).status(201).body_ok(/updated/).then(function () {
+ }).status(201).body_ok(/updated/).then(function() {
return server.request({
method: 'GET',
- uri: '/-/package/testexp_tags2/dist-tags',
- }).status(200).then(function (body) {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ }).status(200).then(function(body) {
assert.deepEqual(body,
- { foo: '0.1.2',
+ {foo: '0.1.2',
quux: '0.1.0',
- latest: '0.1.3alpha' })
- })
- })
- })
+ latest: '0.1.3alpha'});
+ });
+ });
+ });
- it('adding a tag', function () {
+ it('adding a tag', function() {
return server.request({
method: 'PUT',
- uri: '/-/package/testexp_tags2/dist-tags/foo',
- json: '0.1.3alpha',
- }).status(201).body_ok(/tagged/).then(function () {
+ uri: '/-/package/testexp_tags2/dist-tags/foo',
+ json: '0.1.3alpha',
+ }).status(201).body_ok(/tagged/).then(function() {
return server.request({
method: 'GET',
- uri: '/-/package/testexp_tags2/dist-tags',
- }).status(200).then(function (body) {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ }).status(200).then(function(body) {
assert.deepEqual(body,
- { foo: '0.1.3alpha',
+ {foo: '0.1.3alpha',
bar: '0.1.1alpha',
baz: '0.1.2',
- latest: '0.1.3alpha' })
- })
- })
- })
+ latest: '0.1.3alpha'});
+ });
+ });
+ });
- it('removing a tag', function () {
+ it('removing a tag', function() {
return server.request({
method: 'DELETE',
- uri: '/-/package/testexp_tags2/dist-tags/foo',
- }).status(201).body_ok(/removed/).then(function () {
+ uri: '/-/package/testexp_tags2/dist-tags/foo',
+ }).status(201).body_ok(/removed/).then(function() {
return server.request({
method: 'GET',
- uri: '/-/package/testexp_tags2/dist-tags',
- }).status(200).then(function (body) {
+ uri: '/-/package/testexp_tags2/dist-tags',
+ }).status(200).then(function(body) {
assert.deepEqual(body,
- { bar: '0.1.1alpha',
+ {bar: '0.1.1alpha',
baz: '0.1.2',
- latest: '0.1.3alpha' })
- })
- })
- })
- })
-}
+ latest: '0.1.3alpha'});
+ });
+ });
+ });
+ });
+};
diff --git a/test/unit/config_def.js b/test/unit/config_def.js
index c3c0caae8..d540f62d7 100644
--- a/test/unit/config_def.js
+++ b/test/unit/config_def.js
@@ -1,8 +1,9 @@
+'use strict';
describe('config.yaml', function() {
it('should be parseable', function() {
- var source = require('fs').readFileSync(__dirname + '/../../conf/default.yaml', 'utf8')
- require('js-yaml').safeLoad(source)
- })
-})
+ let source = require('fs').readFileSync(__dirname + '/../../conf/default.yaml', 'utf8');
+ require('js-yaml').safeLoad(source);
+ });
+});
diff --git a/test/unit/listen_addr.js b/test/unit/listen_addr.js
index dc2fd2ed8..7bfbd61ab 100644
--- a/test/unit/listen_addr.js
+++ b/test/unit/listen_addr.js
@@ -1,42 +1,44 @@
-var assert = require('assert')
-var parse = require('../../lib/utils').parse_address
+'use strict';
+
+let assert = require('assert');
+let parse = require('../../lib/utils').parse_address;
describe('Parse address', function() {
function addTest(what, proto, host, port) {
it(what, function() {
if (proto === null) {
- assert.strictEqual(parse(what), null)
+ assert.strictEqual(parse(what), null);
} else if (port) {
assert.deepEqual(parse(what), {
proto: proto,
host: host,
port: port,
- })
+ });
} else {
assert.deepEqual(parse(what), {
proto: proto,
path: host,
- })
+ });
}
- })
+ });
}
- addTest('4873', 'http', 'localhost', '4873')
- addTest(':4873', 'http', 'localhost', '4873')
- addTest('blah:4873', 'http', 'blah', '4873')
- addTest('http://:4873', 'http', 'localhost', '4873')
- addTest('https::4873', 'https', 'localhost', '4873')
- addTest('https:blah:4873', 'https', 'blah', '4873')
- addTest('https://blah:4873/', 'https', 'blah', '4873')
- addTest('[::1]:4873', 'http', '::1', '4873')
- addTest('https:[::1]:4873', 'https', '::1', '4873')
+ addTest('4873', 'http', 'localhost', '4873');
+ addTest(':4873', 'http', 'localhost', '4873');
+ addTest('blah:4873', 'http', 'blah', '4873');
+ addTest('http://:4873', 'http', 'localhost', '4873');
+ addTest('https::4873', 'https', 'localhost', '4873');
+ addTest('https:blah:4873', 'https', 'blah', '4873');
+ addTest('https://blah:4873/', 'https', 'blah', '4873');
+ addTest('[::1]:4873', 'http', '::1', '4873');
+ addTest('https:[::1]:4873', 'https', '::1', '4873');
- addTest('unix:/tmp/foo.sock', 'http', '/tmp/foo.sock')
- addTest('http:unix:foo.sock', 'http', 'foo.sock')
- addTest('https://unix:foo.sock', 'https', 'foo.sock')
+ addTest('unix:/tmp/foo.sock', 'http', '/tmp/foo.sock');
+ addTest('http:unix:foo.sock', 'http', 'foo.sock');
+ addTest('https://unix:foo.sock', 'https', 'foo.sock');
- addTest('blah', null)
- addTest('blah://4873', null)
- addTest('https://blah:4873///', null)
- addTest('unix:1234', 'http', 'unix', '1234') // not unix socket
-})
+ addTest('blah', null);
+ addTest('blah://4873', null);
+ addTest('https://blah:4873///', null);
+ addTest('unix:1234', 'http', 'unix', '1234'); // not unix socket
+});
diff --git a/test/unit/mystreams.js b/test/unit/mystreams.js
index de6894e4b..13ff29dbd 100644
--- a/test/unit/mystreams.js
+++ b/test/unit/mystreams.js
@@ -1,17 +1,19 @@
-var ReadTarball = require('../../lib/streams').ReadTarballStream
+'use strict';
+
+let ReadTarball = require('../../lib/streams').ReadTarballStream;
describe('mystreams', function() {
it('should delay events', function(cb) {
- var test = new ReadTarball()
- test.abort()
+ let test = new ReadTarball();
+ test.abort();
setTimeout(function() {
test.abort = function() {
- cb()
- }
+ cb();
+ };
test.abort = function() {
- throw Error('fail')
- }
- }, 10)
- })
-})
+ throw Error('fail');
+ };
+ }, 10);
+ });
+});
diff --git a/test/unit/no_proxy.js b/test/unit/no_proxy.js
index 317667515..d86ccfb65 100644
--- a/test/unit/no_proxy.js
+++ b/test/unit/no_proxy.js
@@ -1,88 +1,90 @@
-var assert = require('assert')
-var Storage = require('../../lib/up-storage')
+'use strict';
-require('../../lib/logger').setup([])
+let assert = require('assert');
+let Storage = require('../../lib/up-storage');
+
+require('../../lib/logger').setup([]);
function setup(host, config, mainconfig) {
- config.url = host
- return Storage(config, mainconfig)
+ config.url = host;
+ return new Storage(config, mainconfig);
}
describe('Use proxy', function() {
it('should work fine without proxy', function() {
- var x = setup('http://x/x', {}, {})
- assert.equal(x.proxy, null)
- })
+ let x = setup('http://x/x', {}, {});
+ assert.equal(x.proxy, null);
+ });
it('local config should take priority', function() {
- var x = setup('http://x/x', {http_proxy: '123'}, {http_proxy: '456'})
- assert.equal(x.proxy, '123')
- })
+ let x = setup('http://x/x', {http_proxy: '123'}, {http_proxy: '456'});
+ assert.equal(x.proxy, '123');
+ });
it('no_proxy is invalid', function() {
- var x = setup('http://x/x', {http_proxy: '123', no_proxy: false}, {})
- assert.equal(x.proxy, '123')
- var x = setup('http://x/x', {http_proxy: '123', no_proxy: null}, {})
- assert.equal(x.proxy, '123')
- var x = setup('http://x/x', {http_proxy: '123', no_proxy: []}, {})
- assert.equal(x.proxy, '123')
- var x = setup('http://x/x', {http_proxy: '123', no_proxy: ''}, {})
- assert.equal(x.proxy, '123')
- })
+ let x = setup('http://x/x', {http_proxy: '123', no_proxy: false}, {});
+ assert.equal(x.proxy, '123');
+ x = setup('http://x/x', {http_proxy: '123', no_proxy: null}, {});
+ assert.equal(x.proxy, '123');
+ x = setup('http://x/x', {http_proxy: '123', no_proxy: []}, {});
+ assert.equal(x.proxy, '123');
+ x = setup('http://x/x', {http_proxy: '123', no_proxy: ''}, {});
+ assert.equal(x.proxy, '123');
+ });
it('no_proxy - simple/include', function() {
- var x = setup('http://localhost', {http_proxy: '123'}, {no_proxy: 'localhost'})
- assert.equal(x.proxy, undefined)
- })
+ let x = setup('http://localhost', {http_proxy: '123'}, {no_proxy: 'localhost'});
+ assert.equal(x.proxy, undefined);
+ });
it('no_proxy - simple/not', function() {
- var x = setup('http://localhost', {http_proxy: '123'}, {no_proxy: 'blah'})
- assert.equal(x.proxy, '123')
- })
+ let x = setup('http://localhost', {http_proxy: '123'}, {no_proxy: 'blah'});
+ assert.equal(x.proxy, '123');
+ });
it('no_proxy - various, single string', function() {
- var x = setup('http://blahblah', {http_proxy: '123'}, {no_proxy: 'blah'})
- assert.equal(x.proxy, '123')
- var x = setup('http://blah.blah', {}, {http_proxy: '123', no_proxy: 'blah'})
- assert.equal(x.proxy, null)
- var x = setup('http://blahblah', {}, {http_proxy: '123', no_proxy: '.blah'})
- assert.equal(x.proxy, '123')
- var x = setup('http://blah.blah', {http_proxy: '123', no_proxy: '.blah'}, {})
- assert.equal(x.proxy, null)
- var x = setup('http://blah', {http_proxy: '123', no_proxy: '.blah'}, {})
- assert.equal(x.proxy, null)
- var x = setup('http://blahh', {http_proxy: '123', no_proxy: 'blah'}, {})
- assert.equal(x.proxy, '123')
- })
+ let x = setup('http://blahblah', {http_proxy: '123'}, {no_proxy: 'blah'});
+ assert.equal(x.proxy, '123');
+ x = setup('http://blah.blah', {}, {http_proxy: '123', no_proxy: 'blah'});
+ assert.equal(x.proxy, null);
+ x = setup('http://blahblah', {}, {http_proxy: '123', no_proxy: '.blah'});
+ assert.equal(x.proxy, '123');
+ x = setup('http://blah.blah', {http_proxy: '123', no_proxy: '.blah'}, {});
+ assert.equal(x.proxy, null);
+ x = setup('http://blah', {http_proxy: '123', no_proxy: '.blah'}, {});
+ assert.equal(x.proxy, null);
+ x = setup('http://blahh', {http_proxy: '123', no_proxy: 'blah'}, {});
+ assert.equal(x.proxy, '123');
+ });
it('no_proxy - various, array', function() {
- var x = setup('http://blahblah', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'})
- assert.equal(x.proxy, '123')
- var x = setup('http://blah.blah', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'})
- assert.equal(x.proxy, null)
- var x = setup('http://blah.foo', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'})
- assert.equal(x.proxy, null)
- var x = setup('http://foo.baz', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'})
- assert.equal(x.proxy, '123')
- var x = setup('http://blahblah', {http_proxy: '123'}, {no_proxy: ['foo','bar','blah']})
- assert.equal(x.proxy, '123')
- var x = setup('http://blah.blah', {http_proxy: '123'}, {no_proxy: ['foo','bar','blah']})
- assert.equal(x.proxy, null)
- })
+ let x = setup('http://blahblah', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'});
+ assert.equal(x.proxy, '123');
+ x = setup('http://blah.blah', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'});
+ assert.equal(x.proxy, null);
+ x = setup('http://blah.foo', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'});
+ assert.equal(x.proxy, null);
+ x = setup('http://foo.baz', {http_proxy: '123'}, {no_proxy: 'foo,bar,blah'});
+ assert.equal(x.proxy, '123');
+ x = setup('http://blahblah', {http_proxy: '123'}, {no_proxy: ['foo', 'bar', 'blah']});
+ assert.equal(x.proxy, '123');
+ x = setup('http://blah.blah', {http_proxy: '123'}, {no_proxy: ['foo', 'bar', 'blah']});
+ assert.equal(x.proxy, null);
+ });
it('no_proxy - hostport', function() {
- var x = setup('http://localhost:80', {http_proxy: '123'}, {no_proxy: 'localhost'})
- assert.equal(x.proxy, null)
- var x = setup('http://localhost:8080', {http_proxy: '123'}, {no_proxy: 'localhost'})
- assert.equal(x.proxy, null)
- })
+ let x = setup('http://localhost:80', {http_proxy: '123'}, {no_proxy: 'localhost'});
+ assert.equal(x.proxy, null);
+ x = setup('http://localhost:8080', {http_proxy: '123'}, {no_proxy: 'localhost'});
+ assert.equal(x.proxy, null);
+ });
it('no_proxy - secure', function() {
- var x = setup('https://something', {http_proxy: '123'}, {})
- assert.equal(x.proxy, null)
- var x = setup('https://something', {https_proxy: '123'}, {})
- assert.equal(x.proxy, '123')
- var x = setup('https://something', {http_proxy: '456', https_proxy: '123'}, {})
- assert.equal(x.proxy, '123')
- })
-})
+ let x = setup('https://something', {http_proxy: '123'}, {});
+ assert.equal(x.proxy, null);
+ x = setup('https://something', {https_proxy: '123'}, {});
+ assert.equal(x.proxy, '123');
+ x = setup('https://something', {http_proxy: '456', https_proxy: '123'}, {});
+ assert.equal(x.proxy, '123');
+ });
+});
diff --git a/test/unit/parse_interval.js b/test/unit/parse_interval.js
index f1e9ac643..c0567be4a 100644
--- a/test/unit/parse_interval.js
+++ b/test/unit/parse_interval.js
@@ -1,34 +1,36 @@
-var assert = require('assert')
-var parse_interval = require('../../lib/config').parse_interval
+'use strict';
+
+let assert = require('assert');
+let parse_interval = require('../../lib/config').parse_interval;
describe('Parse interval', function() {
function add_test(str, res) {
it('parse ' + str, function() {
if (res === null) {
assert.throws(function() {
- console.log(parse_interval(str))
- })
+ console.log(parse_interval(str));
+ });
} else {
- assert.strictEqual(parse_interval(str), res)
+ assert.strictEqual(parse_interval(str), res);
}
- })
+ });
}
- add_test(12345, 12345000)
- add_test('1000', 1000000)
- add_test('1.5s', 1500)
- add_test('25ms', 25)
- add_test('2m', 2*1000*60)
- add_test('3h', 3*1000*60*60)
- add_test('0.5d', 0.5*1000*60*60*24)
- add_test('0.5w', 0.5*1000*60*60*24*7)
- add_test('1M', 1000*60*60*24*30)
- add_test('5s 20ms', 5020)
- add_test('1y', 1000*60*60*24*365)
- add_test('1y 5', null)
- add_test('1m 1m', null)
- add_test('1m 1y', null)
- add_test('1y 1M 1w 1d 1h 1m 1s 1ms', 34822861001)
- add_test(' 5s 25ms ', 5025)
-})
+ add_test(12345, 12345000);
+ add_test('1000', 1000000);
+ add_test('1.5s', 1500);
+ add_test('25ms', 25);
+ add_test('2m', 2*1000*60);
+ add_test('3h', 3*1000*60*60);
+ add_test('0.5d', 0.5*1000*60*60*24);
+ add_test('0.5w', 0.5*1000*60*60*24*7);
+ add_test('1M', 1000*60*60*24*30);
+ add_test('5s 20ms', 5020);
+ add_test('1y', 1000*60*60*24*365);
+ add_test('1y 5', null);
+ add_test('1m 1m', null);
+ add_test('1m 1y', null);
+ add_test('1y 1M 1w 1d 1h 1m 1s 1ms', 34822861001);
+ add_test(' 5s 25ms ', 5025);
+});
diff --git a/test/unit/partials/config.js b/test/unit/partials/config.js
index c6394f260..82f9cff69 100644
--- a/test/unit/partials/config.js
+++ b/test/unit/partials/config.js
@@ -1,4 +1,6 @@
-var config = {
+'use strict';
+
+let config = {
storage: __dirname + '/test-storage',
packages: {
'*': {
@@ -6,8 +8,8 @@ var config = {
},
},
logs: [
- {type: 'stdout', format: 'pretty', level: 'fatal'}
+ {type: 'stdout', format: 'pretty', level: 'fatal'},
],
-}
+};
module.exports = config;
diff --git a/test/unit/partials/test-plugin-storage/invalid-plugin-sanity/index.js b/test/unit/partials/test-plugin-storage/invalid-plugin-sanity/index.js
index 97336662e..5c391fd12 100644
--- a/test/unit/partials/test-plugin-storage/invalid-plugin-sanity/index.js
+++ b/test/unit/partials/test-plugin-storage/invalid-plugin-sanity/index.js
@@ -3,6 +3,6 @@ function ValidVerdaccioPlugin() {
// not valid method
authenticate__: function(){}
}
-};
+}
module.exports = ValidVerdaccioPlugin;
diff --git a/test/unit/partials/test-plugin-storage/verdaccio-plugin/index.js b/test/unit/partials/test-plugin-storage/verdaccio-plugin/index.js
index 540501af0..eaa9006e0 100644
--- a/test/unit/partials/test-plugin-storage/verdaccio-plugin/index.js
+++ b/test/unit/partials/test-plugin-storage/verdaccio-plugin/index.js
@@ -2,6 +2,6 @@ function ValidVerdaccioPlugin() {
return {
authenticate: function(){}
}
-};
+}
module.exports = ValidVerdaccioPlugin;
diff --git a/test/unit/search.js b/test/unit/search.js
index 9b18d0e02..837bc8f69 100644
--- a/test/unit/search.js
+++ b/test/unit/search.js
@@ -1,39 +1,40 @@
-var assert = require('assert');
-var Search = require('../../lib/search');
-var Storage = require('../../lib/storage');
-var config_hash = require('./partials/config');
-var Config = require('../../lib/config');
+'use strict';
+
+let assert = require('assert');
+let Search = require('../../lib/search');
+let Storage = require('../../lib/storage');
+let config_hash = require('./partials/config');
+let Config = require('../../lib/config');
require('../../lib/logger').setup([]);
-var packages = [
+let packages = [
{
name: 'test1',
description: 'description',
_npmUser: {
name: 'test_user',
- }
+ },
},
{
name: 'test2',
description: 'description',
_npmUser: {
name: 'test_user',
- }
+ },
},
{
name: 'test3',
description: 'description',
_npmUser: {
name: 'test_user',
- }
- }
-]
+ },
+ },
+];
describe('search', function() {
-
before(function() {
- var config = Config(config_hash);
+ let config = Config(config_hash);
this.storage = new Storage(config);
Search.configureStorage(this.storage);
packages.map(function(item) {
@@ -42,24 +43,23 @@ describe('search', function() {
});
it('search query item', function() {
- var result = Search.query('t');
+ let result = Search.query('t');
assert(result.length === 3);
});
it('search remove item', function() {
- var item = {
+ let item = {
name: 'test6',
description: 'description',
_npmUser: {
name: 'test_user',
- }
+ },
};
Search.add(item);
- var result = Search.query('test6');
+ let result = Search.query('test6');
assert(result.length === 1);
Search.remove(item.name);
- var result = Search.query('test6');
+ result = Search.query('test6');
assert(result.length === 0);
});
-
});
diff --git a/test/unit/st_merge.js b/test/unit/st_merge.js
index 8c98ba453..8c023be1d 100644
--- a/test/unit/st_merge.js
+++ b/test/unit/st_merge.js
@@ -1,41 +1,43 @@
-var assert = require('assert')
-var semver_sort = require('../../lib/utils').semver_sort
-var merge = require('../../lib/storage')._merge_versions
+'use strict';
-require('../../lib/logger').setup([])
+let assert = require('assert');
+let semver_sort = require('../../lib/utils').semver_sort;
+let merge = require('../../lib/storage')._merge_versions;
+
+require('../../lib/logger').setup([]);
describe('Merge', function() {
it('simple', function() {
- var x = {
- versions: {a:1,b:1,c:1},
+ let x = {
+ 'versions': {a: 1, b: 1, c: 1},
'dist-tags': {},
- }
- merge(x, {versions: {a:2,q:2}})
+ };
+ merge(x, {versions: {a: 2, q: 2}});
assert.deepEqual(x, {
- versions: {a:1,b:1,c:1,q:2},
+ 'versions': {a: 1, b: 1, c: 1, q: 2},
'dist-tags': {},
- })
- })
+ });
+ });
it('dist-tags - compat', function() {
- var x = {
- versions: {},
- 'dist-tags': {q:'1.1.1',w:'2.2.2'},
- }
- merge(x, {'dist-tags':{q:'2.2.2',w:'3.3.3',t:'4.4.4'}})
+ let x = {
+ 'versions': {},
+ 'dist-tags': {q: '1.1.1', w: '2.2.2'},
+ };
+ merge(x, {'dist-tags': {q: '2.2.2', w: '3.3.3', t: '4.4.4'}});
assert.deepEqual(x, {
- versions: {},
- 'dist-tags': {q:'2.2.2',w:'3.3.3',t:'4.4.4'},
- })
- })
+ 'versions': {},
+ 'dist-tags': {q: '2.2.2', w: '3.3.3', t: '4.4.4'},
+ });
+ });
it('semver_sort', function() {
- assert.deepEqual(semver_sort(['1.2.3','1.2','1.2.3a','1.2.3c','1.2.3-b']),
- [ '1.2.3a',
+ assert.deepEqual(semver_sort(['1.2.3', '1.2', '1.2.3a', '1.2.3c', '1.2.3-b']),
+ ['1.2.3a',
'1.2.3-b',
'1.2.3c',
- '1.2.3' ]
- )
- })
-})
+ '1.2.3']
+ );
+ });
+});
diff --git a/test/unit/tag_version.js b/test/unit/tag_version.js
index 036881d80..4616ffe93 100644
--- a/test/unit/tag_version.js
+++ b/test/unit/tag_version.js
@@ -1,44 +1,45 @@
-var assert = require('assert')
-var tag_version = require('../../lib/utils').tag_version
+'use strict';
-require('../../lib/logger').setup([])
+let assert = require('assert');
+let tag_version = require('../../lib/utils').tag_version;
+
+require('../../lib/logger').setup([]);
describe('tag_version', function() {
it('add new one', function() {
- var x = {
- versions: {},
+ let x = {
+ 'versions': {},
'dist-tags': {},
- }
- assert(tag_version(x, '1.1.1', 'foo', {}))
+ };
+ assert(tag_version(x, '1.1.1', 'foo', {}));
assert.deepEqual(x, {
- versions: {},
+ 'versions': {},
'dist-tags': {foo: '1.1.1'},
- })
- })
+ });
+ });
it('add (compat)', function() {
- var x = {
- versions: {},
+ let x = {
+ 'versions': {},
'dist-tags': {foo: '1.1.0'},
- }
- assert(tag_version(x, '1.1.1', 'foo'))
+ };
+ assert(tag_version(x, '1.1.1', 'foo'));
assert.deepEqual(x, {
- versions: {},
+ 'versions': {},
'dist-tags': {foo: '1.1.1'},
- })
- })
+ });
+ });
it('add fresh tag', function() {
- var x = {
- versions: {},
+ let x = {
+ 'versions': {},
'dist-tags': {foo: '1.1.0'},
- }
- assert(tag_version(x, '1.1.1', 'foo'))
+ };
+ assert(tag_version(x, '1.1.1', 'foo'));
assert.deepEqual(x, {
- versions: {},
+ 'versions': {},
'dist-tags': {foo: '1.1.1'},
- })
- })
-
-})
+ });
+ });
+});
diff --git a/test/unit/toplevel.js b/test/unit/toplevel.js
index 1959b3cb8..59199e8a1 100644
--- a/test/unit/toplevel.js
+++ b/test/unit/toplevel.js
@@ -1,45 +1,47 @@
-var assert = require('assert')
-var express = require('express')
-var request = require('request')
-var rimraf = require('rimraf')
-var verdaccio = require('../../')
-var config = require('./partials/config');
+'use strict';
+
+let assert = require('assert');
+let express = require('express');
+let request = require('request');
+let rimraf = require('rimraf');
+let verdaccio = require('../../');
+let config = require('./partials/config');
describe('toplevel', function() {
- var port
+ let port;
before(function(done) {
- rimraf(__dirname + '/test-storage', done)
- })
+ rimraf(__dirname + '/test-storage', done);
+ });
before(function(done) {
- var app = express()
- app.use(verdaccio(config))
+ let app = express();
+ app.use(verdaccio(config));
- var server = require('http').createServer(app)
+ let server = require('http').createServer(app);
server.listen(0, function() {
- port = server.address().port
- done()
- })
- })
+ port = server.address().port;
+ done();
+ });
+ });
it('should respond on /', function(done) {
request({
url: 'http://localhost:' + port + '/',
}, function(err, res, body) {
- assert.equal(err, null)
- assert(body.match(/Verdaccio<\/title>/))
- done()
- })
- })
+ assert.equal(err, null);
+ assert(body.match(/Verdaccio<\/title>/));
+ done();
+ });
+ });
it('should respond on /whatever', function(done) {
request({
url: 'http://localhost:' + port + '/whatever',
}, function(err, res, body) {
- assert.equal(err, null)
- assert(body.match(/no such package available/))
- done()
- })
- })
-})
+ assert.equal(err, null);
+ assert(body.match(/no such package available/));
+ done();
+ });
+ });
+});
diff --git a/test/unit/utils.js b/test/unit/utils.js
index 3b3009c53..9794e50f1 100644
--- a/test/unit/utils.js
+++ b/test/unit/utils.js
@@ -1,42 +1,44 @@
-var assert = require('assert')
-var validate = require('../../lib/utils').validate_name
+'use strict';
+
+let assert = require('assert');
+let validate = require('../../lib/utils').validate_name;
describe('Validate', function() {
it('good ones', function() {
- assert( validate('verdaccio') )
- assert( validate('some.weird.package-zzz') )
- assert( validate('old-package@0.1.2.tgz') )
- })
+ assert( validate('verdaccio') );
+ assert( validate('some.weird.package-zzz') );
+ assert( validate('old-package@0.1.2.tgz') );
+ });
it('uppercase', function() {
- assert( validate('EVE') )
- assert( validate('JSONStream') )
- })
+ assert( validate('EVE') );
+ assert( validate('JSONStream') );
+ });
it('no package.json', function() {
- assert( !validate('package.json') )
- })
+ assert( !validate('package.json') );
+ });
it('no path seps', function() {
- assert( !validate('some/thing') )
- assert( !validate('some\\thing') )
- })
+ assert( !validate('some/thing') );
+ assert( !validate('some\\thing') );
+ });
it('no hidden', function() {
- assert( !validate('.bin') )
- })
+ assert( !validate('.bin') );
+ });
it('no reserved', function() {
- assert( !validate('favicon.ico') )
- assert( !validate('node_modules') )
- assert( !validate('__proto__') )
- })
+ assert( !validate('favicon.ico') );
+ assert( !validate('node_modules') );
+ assert( !validate('__proto__') );
+ });
it('other', function() {
- assert( !validate('pk g') )
- assert( !validate('pk\tg') )
- assert( !validate('pk%20g') )
- assert( !validate('pk+g') )
- assert( !validate('pk:g') )
- })
-})
+ assert( !validate('pk g') );
+ assert( !validate('pk\tg') );
+ assert( !validate('pk%20g') );
+ assert( !validate('pk+g') );
+ assert( !validate('pk:g') );
+ });
+});
diff --git a/test/unit/validate_all.js b/test/unit/validate_all.js
index 662d41b6b..cf88af0e3 100644
--- a/test/unit/validate_all.js
+++ b/test/unit/validate_all.js
@@ -1,39 +1,42 @@
+'use strict';
+
// ensure that all arguments are validated
-var assert = require('assert')
+let assert = require('assert');
-describe('index.js app', test('index.js'))
-describe('index-api.js app', test('index-api.js'))
-describe('index-web.js app', test('index-web.js'))
+describe('index.js app', test('index.js'));
+describe('index-api.js app', test('index-api.js'));
+describe('index-web.js app', test('index-web.js'));
function test(file) {
return function() {
- var source = require('fs').readFileSync(__dirname + '/../../lib/' + file, 'utf8')
+ let source = require('fs').readFileSync(__dirname + '/../../lib/' + file, 'utf8');
- var very_scary_regexp = /\n\s*app\.(\w+)\s*\(\s*(("[^"]*")|('[^']*'))\s*,/g
- var m
- var params = {}
+ let very_scary_regexp = /\n\s*app\.(\w+)\s*\(\s*(("[^"]*")|('[^']*'))\s*,/g;
+ let m;
+ let params = {};
while ((m = very_scary_regexp.exec(source)) != null) {
- if (m[1] === 'set') continue
+ if (m[1] === 'set') continue;
- var inner = m[2].slice(1, m[2].length-1)
- var t
+ let inner = m[2].slice(1, m[2].length-1);
+ var t;
inner.split('/').forEach(function(x) {
+ t = x.match(/^:([^?:]*)\??$/);
if (m[1] === 'param') {
- params[x] = 'ok'
- } else if (t = x.match(/^:([^?:]*)\??$/)) {
- params[t[1]] = params[t[1]] || m[0].trim()
+ params[x] = 'ok';
+ } else if (t) {
+ params[t[1]] = params[t[1]] || m[0].trim();
}
- })
+ });
}
Object.keys(params).forEach(function(param) {
it('should validate ":'+param+'"', function() {
- assert.equal(params[param], 'ok')
- })
- })
- }
+ assert.equal(params[param], 'ok');
+ });
+ });
+ };
}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 000000000..006914cf1
Binary files /dev/null and b/yarn.lock differ