Skip to content
Permalink
Browse files

[dist] code and tests

  • Loading branch information...
jcrugzz committed Nov 30, 2016
1 parent 547efa8 commit 3f583a753b7d6334e8c7feab856ab6b33083c515
Showing with 4,467 additions and 0 deletions.
  1. +8 −0 bin/server
  2. +68 −0 config.example.json
  3. +112 −0 lib/app.js
  4. +31 −0 lib/checkmate.js
  5. +78 −0 lib/classifier.js
  6. +20 −0 lib/index.js
  7. +225 −0 lib/loading-bay.js
  8. +82 −0 lib/middlewares/debug.js
  9. +29 −0 lib/middlewares/error.js
  10. +71 −0 lib/middlewares/index.js
  11. +12 −0 lib/npm/middleware.js
  12. +73 −0 lib/npm/params.js
  13. +30 −0 lib/npm/preboot.js
  14. +460 −0 lib/npm/publisher.js
  15. +229 −0 lib/npm/routes.js
  16. +141 −0 lib/npm/tagger.js
  17. +28 −0 lib/preboots/agents.js
  18. +13 −0 lib/preboots/bffs.js
  19. +16 −0 lib/preboots/carpenter.js
  20. +28 −0 lib/preboots/index.js
  21. +13 −0 lib/preboots/loading-bay.js
  22. +29 −0 lib/preboots/wrhs-models.js
  23. +56 −0 lib/routes/assets.js
  24. +172 −0 lib/routes/builds.js
  25. +29 −0 lib/routes/checks.js
  26. +18 −0 lib/routes/index.js
  27. +26 −0 lib/routes/packages.js
  28. +58 −0 lib/routes/params.js
  29. +89 −0 package.json
  30. +8 −0 scripts/import-npm-routes.js
  31. +12 −0 test/config/development.json
  32. +8 −0 test/fixtures/checks/bad.js
  33. +8 −0 test/fixtures/checks/good.js
  34. +13 −0 test/fixtures/checks/simple.js
  35. +5 −0 test/fixtures/mock-npmrc
  36. BIN test/fixtures/packages/valid-guac-widget.tgz
  37. +40 −0 test/fixtures/payloads/@good-work.json
  38. +40 −0 test/fixtures/payloads/@scope-fail.json
  39. +1 −0 test/fixtures/payloads/my-package-0.0.1.json
  40. +1 −0 test/fixtures/payloads/npm-publish-split-stream-0.0.0.json
  41. +44 −0 test/fixtures/payloads/what-is-happening-1.10.1.json
  42. +157 −0 test/helpers.js
  43. +66 −0 test/integration/app.test.js
  44. +58 −0 test/integration/npm/econn.test.js
  45. +131 −0 test/integration/npm/publish.test.js
  46. +264 −0 test/integration/npm/routes.test.js
  47. +121 −0 test/integration/routes/assets.test.js
  48. +193 −0 test/integration/routes/builds.test.js
  49. +49 −0 test/integration/routes/debug.test.js
  50. +206 −0 test/macros.js
  51. +2 −0 test/mocha.opts
  52. +44 −0 test/mocks/child-process.js
  53. +46 −0 test/mocks/file-request.js
  54. +72 −0 test/mocks/hyperquest.js
  55. +85 −0 test/mocks/index.js
  56. +166 −0 test/mocks/registry.js
  57. +19 −0 test/unit/app.test.js
  58. +153 −0 test/unit/checkmate.test.js
  59. +177 −0 test/unit/npm/publisher.test.js
  60. +34 −0 test/unit/preboot/agents.test.js
@@ -0,0 +1,8 @@
#!/usr/bin/env node

require('../lib').start(function (err, app) {
if (err) {
return app.log.error('Error starting warehouse', err);
}
app.log.info('Warehouse started on %s', app.config.get('http'));
});
@@ -0,0 +1,68 @@
{
"http": 8080,
"bffs": {
"prefix": "wrhs",
"cdn": {
"prod": {
"pkgcloud": {
"provider": "amazon",
"endpoint": "aws.amazon.net",
"keyId": "fake",
"key": "fake",
"forcePathBucket": true
},
"url": "https://mycloudfrontURL.com"
},
"test": {
"pkgcloud": {
"provider": "amazon",
"endpoint": "aws.amazon.net",
"keyId": "fake",
"key": "fake",
"forcePathBucket": true
},
"url": "https://mycloudfrontURL.com"
},
"dev": {
"pkgcloud": {
"provider": "amazon",
"endpoint": "aws.amazon.net",
"keyId": "fake",
"key": "fake",
"forcePathBucket": true
},
"url": "https://mycloudfrontURL.com/"
}
}
},
"npm": {
"debugChildren": true,
"urls": {
"read": "http://registry.npmjs.org",
"write": {
"default": "http://localhost:8081"
}
}
},
"builder": {
"url": {
"hostname": "127.0.0.1",
"protocol": "http",
"port": 1337
}
},
"database": {
"config": {
"keyspace": "warehouse_dev",
"user": "cassandra",
"password": "cassandra",
"hosts": [
"127.0.0.1"
],
"keyspaceOptions": {
"class": "SimpleStrategy",
"replication_factor": 1
}
}
}
}
@@ -0,0 +1,112 @@
'use strict';
/* eslint: no-process-env: 0 */

var util = require('util'),
url = require('url'),
errs = require('errs'),
httpProxy = require('http-proxy'),
slay = require('slay');

/**
* @constructor App
* @param {string} root - Root directory of app
* @param {Object} options - configuration options
* @returns {undefined}
*/
var App = module.exports = function App(root, options) {
slay.App.call(this, root, options);

this.env = process.env.NODE_ENV || 'development';
this.after('close', this._onClose.bind(this));
//
// Setup our application proxy instance, mainly for making request
// to our npm target.
//
// TODO: these options should be more configurable.
//
this.httpProxy = httpProxy.createProxy({
changeOrigin: true,
secure: false
});

this.agents = {};
};

util.inherits(App, slay.App);

/*
* function npmProxy (req, res, next)
* Attempts to proxy the specified `req` and `res` to a known
* npm target.
*
* Remark: this is a *prototypal* method for performance reasons.
*/
App.prototype.npmProxy = function (req, res, next) {
var self = this;
var attempt;

if (!this._npmTarget) {
attempt = this.config.get('npm:urls:read');
if (!attempt) {
return next(errs.create({
message: 'Not found: ' + req.url,
status: 404
}));
}

this._npmTarget = attempt;
}

req.log.info('Proxy to npm', {
target: this._npmTarget,
headers: req.headers,
url: req.url
});

//
// This should be handled cleaner in http-proxy when the target has auth
// but that may be a breaking change so lets manually do it here FOR NOW.
//
var parsed = url.parse(this._npmTarget);
var auth = parsed.auth;
var proto = parsed.protocol;

//
// TODO: Check the set of know npm proxy targets
// and to not continue iff. the req.url does not
// match those routes.
//
this.httpProxy.web(req, res, {
auth: auth,
target: this._npmTarget,
agent: this.agents[proto]
}, function httpProxyError(e) {
self.log.error('Proxy to npm', {
error: e.message,
target: self._npmTarget,
headers: req.headers,
url: req.url
});

next(e);
});
};

/**
* @function _onClose
* @param {slay.App} app - App object
* @param {Object} options - Options Object
* @param {function} next - continuation object
* Closes any open Cassandra connections and agents associated with this instance.
* Used by the slay `close` interceptor.
* @returns {undefined}
*/
App.prototype._onClose = function (app, options, next) {
if (!this.datastar) return;

Object.keys(this.agents).forEach(key => {
this.agents[key].destroy();
});

this.datastar.close(next);
};
@@ -0,0 +1,31 @@
'use strict';

var failure = require('failure');

/*
* Kills the process with the specified message
*/
function dieWith(msg) {
process.send(failure(new Error(msg)));
process.send({ __checkmate: true });
}

process.on('message', function message(data) {
if (!data.check) {
return dieWith('{ check } is required data using `.send()`');
} else if (!data.payload) {
return dieWith('{ payload } is required data using `.send()`');
}

var check;
try {
check = require(data.check);
} catch (ex) {
return dieWith(ex.message);
}

check(Object.freeze(data.payload), function checked(err) {
if (err) process.send(failure(err));
process.send({ __checkmate: true });
});
});
@@ -0,0 +1,78 @@
'use strict';

var merge = require('lodash.merge');

/**
* Constructor function for the Classifier responsible for mapping
* package.json keywords onto a fully resolved set of script paths
* representing checks to execute for a valid publish.
*
* @param {Object} opts Options for classification.
*/
var Classifier = module.exports = function Classifier(opts) {
this.classification = opts.keywords || {};
this.projects = Object.keys(opts.projects || {})
.reduce(function (acc, type) {
acc[type] = opts.projects[type].map(function (pkg) {
return require.resolve(pkg);
});

return acc;
}, {})
};

/**
* Find the correct set of checks for the provided package.json
*
* @param {Object} data Package.json which we need to classify.
* @param {Object} options Define additional classifications or special keywords.
* @returns {Array} Set of checks to execute
* @api public
*/
Classifier.prototype.getChecks = function (data, options) {
var project = this.getProject(data, options);
return this.projects[project] || [];
};

/**
* Find the correct project on the provided package.json.
*
* @param {Object} data Package.json which we need to classify.
* @param {Object} options Define additional classifications or special keywords.
* @returns {String} Empty string indicates global usage.
* @api public
*/
Classifier.prototype.getProject = function (data, options) {
options = options || {};

//
// Allow additional rules to be defined and merge against the default.
//
var classy = merge(this.classification, options.classification),
keyword = options.keyword || 'check',
match = '';

//
// The classification can also be read directly from the data.
// Allow opt-in for a `keyword`. This defaults to the `check` property.
//
if (data[keyword] in classy) return data[keyword];

//
// Check if there are keywords in the package.json that gives some intel on
// which project/team created these packages.
//
if (!Array.isArray(data.keywords)) data.keywords = [];

Object.keys(classy).some(function each(project) {
var keywords = classy[project];

if (keywords.some(function some(keyword) {
return !!~data.keywords.indexOf(keyword);
})) return !!(match = project);

return false;
});

return match;
};
@@ -0,0 +1,20 @@
'use strict';

var path = require('path');
var App = exports.App = require('./app');

/*
* Create a new application and start it.
*/
exports.start = function (options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}

var app = new App(path.join(__dirname, '..'), options);
app.start(function (err) {
if (err) { return callback(err); }
callback(null, app);
});
};
Oops, something went wrong.

0 comments on commit 3f583a7

Please sign in to comment.
You can’t perform that action at this time.