Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 31 additions & 83 deletions bin/cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ var defaultConfig = require('../config/default'),
snpm = require('../lib'),
url = require('url'),
fs = require('fs'),
path = require('path'),
getPkgs = require('npm-registry-packages');
path = require('path')
util = require('util');

process.title = 'smart-private-npm';

Expand Down Expand Up @@ -39,128 +39,76 @@ if (argv.help) {
// TODO: Replace with diagnostic
var winston = require('winston');

var log = new winston.Logger({
var config = argv.config ? require(path.resolve(process.cwd(), argv.config)) : {};

var log = config.log = config.log || new winston.Logger({
transports: [
new (winston.transports.Console)({ level: argv.loglevel, colorize: true })
]
});

var config = argv.config ? require(path.resolve(process.cwd(), argv.config)) : {};

config.ip = argv.i;

//
// TODO: A better way of merging the defaults with the cli flags
// taking precendence
//
config.private = argv.private || config.private || defaultConfig.private;

config.public = argv.public || config.public || defaultConfig.public;

config.http = config.http || defaultConfig.http;

config.https = config.https || null;

config.exclude = argv.exclude || config.exclude || defaultConfig.exclude;

config.rewrites = config.rewrites || require('../config/rewrites');

config.transparent = argv.transparent || config.transparent || false;


if (argv.config) {
log.verbose('config => %s', argv.config);
}
log.verbose('private registry => %s', config.private);
log.verbose('public registry => %s', config.public);
log.verbose('http => %s', ''+config.http);
log.verbose('https => '+(config.https ? config.https : 'null'));
log.verbose('excludes =>', config.exclude);
log.verbose('transparent =>', config.transparent);
log.verbose('ignore-private =>', config.ip);


if (typeof config.public === "string") {
config.public = url.parse(config.public);
}
if (typeof config.private === "string") {
config.private = url.parse(config.private);
}

var proxyOpts = {
rewrites: config.rewrites,
var snpmOpts = {
rewrites: null,
proxy: {
npm: config.public,
npm: null,
policy: {
npm: config.private,
npm: null,
private: {},
blacklist: {},
transparent: config.transparent
transparent: false
},
log: log
log: null
},
http: config.http,
https: config.https,
log: log
http: null,
https: null,
log: null
};

if (config.blacklist) {
proxyOpts.proxy.policy.blacklist = config.blacklist;
}
snpmOpts = util._extend(snpmOpts, defaultConfig, config, argv);
delete snpmOpts.config;

if (config.whitelist) {
proxyOpts.proxy.policy.whitelist = config.whitelist;
if (argv.config) {
log.verbose('config => %s', argv.config);
}

if (config.ip === true) {
log.verbose('private registry => %s', snpmOpts.proxy.policy.npm);
log.verbose('public registry => %s', snpmOpts.npm);
log.verbose('http => %s', ''+snpmOpts.http);
log.verbose('https => '+(snpmOpts.https ? snpmOpts.https : 'null'));
log.verbose('excludes =>', snpmOpts.exclude);
log.verbose('transparent =>', snpmOpts.proxy.transparent);
log.verbose('ignore-private =>', snpmOpts.ip);

if (snpmOpts.ip === true) {
getPkgs = function(a, cb) {
process.nextTick(function() {
cb(null, []);
});
};
}

getPkgs(config.private.href, function(err, pkgs) {
snpm.getPkgs(snpmOpts, function(err, privatePkgs) {
if (err) {
if (err.code && err.code === 'ECONNREFUSED') {
log.error('Error loading private packages', err.message);
log.error('Is your private registry running and accessible at [%s]?', config.private);
log.error('Is your private registry running and accessible at [%s]?', snpmOpts.proxy.policy.npm);
} else {
log.error('Error loading private packages', { err: err });
}

return process.exit(1);
}

if (!config.filter) {
pkgs = pkgs.filter(function(f) {
return (!(~config.exclude.indexOf(f)));
});
}

var privatePkgs = {},
len = pkgs.length;

if (!config.ip) {
for (var i=0; i<len; i++) {
var pkg = pkgs[i];
privatePkgs[pkg] = 1;
}

config.exclude.forEach(function(e) {
log.verbose('excluding package: '+e);
if (privatePkgs.hasOwnProperty(e)) {
delete privatePkgs[e];
}
});

log.verbose('loaded private packages', privatePkgs);
} else {
log.verbose('ignoring packages from private registry');
}

proxyOpts.proxy.policy.private = privatePkgs;
snpm.createServer(proxyOpts, function(err, servers) {
snpmOpts.proxy.policy.private = privatePkgs;
snpm.createServer(snpmOpts, function(err, servers) {
if (err) {
log.error('error starting private npm', { err: err });
log.error('servers: %j', Object.keys(servers));
Expand Down
26 changes: 17 additions & 9 deletions config/default.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//
// Default rewrites for routes
//
exports.rewrites = require('./rewrites');

//
// Default CouchDB documents to exclude
//
Expand All @@ -9,15 +14,18 @@ exports.exclude = [
'error: forbidden',
];

//
// Private npm registry url
//
exports.private = 'http://localhost:5984';

//
// Public npm registry url
//
exports.public = 'https://registry.nodejitsu.com';
exports.proxy = {
//
// Public npm registry url
//
npm: 'https://registry.nodejitsu.com',
policy: {
//
// Private npm registry url
//
npm: 'http://localhost:5984'
}
};

//
// Function to filter excluded documents
Expand Down
52 changes: 51 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

var createServers = require('create-servers'),
director = require('director');
director = require('director'),
getPkgs = require('npm-registry-packages');

var patterns = {
packageAnd: /\/([_\.\(\)!\\ %@&a-zA-Z0-9-]+)\/.*/,
Expand Down Expand Up @@ -178,3 +179,52 @@ exports.createRouter = function createRouter(options, callback) {
router.proxy = proxy;
return router;
};

//
// ### function getPkgs (options, callback)
// #### @options {Object} Options for starting the proxy
// #### - log {function} Logging function to use.
// #### - exclude {Array} Default CouchDB documents to exclude.
// #### - filter {function} Filter function for CouchDB documente exclusion.
// #### - ip {boolean} Whether to ignore packages from private registry.
//
exports.getPkgs = function(config, cb) {
url = config.private || config.proxy.policy.npm;
if (url.href) url = url.href;

getPkgs(url, function(err, pkgs) {
if (err) {
return cb(err);
}

if (!config.filter) {
pkgs = pkgs.filter(function(f) {
return (!(~config.exclude.indexOf(f)));
});
}

var privatePkgs = {},
len = pkgs.length,
log = config.log;

if (!config.ip) {
for (var i=0; i<len; i++) {
var pkg = pkgs[i];
privatePkgs[pkg] = 1;
}

config.exclude.forEach(function(e) {
log.info('[getPkgs] excluding package: '+e);
if (privatePkgs.hasOwnProperty(e)) {
delete privatePkgs[e];
}
});

log.info('[getPkgs] loaded private packages', privatePkgs);
} else {
log.info('[getPkgs] ignoring packages from private registry');
}

cb(null, privatePkgs);
});
};