Skip to content

Commit

Permalink
Merge pull request #113 from nymag/auto-bootstrap
Browse files Browse the repository at this point in the history
auto-bootstrap
  • Loading branch information
TakenPilot committed Jul 31, 2015
2 parents be3baf8 + 2060181 commit 5b03af3
Show file tree
Hide file tree
Showing 12 changed files with 421 additions and 145 deletions.
72 changes: 68 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,77 @@
// this will set up things
'use strict';

var app = require('express')(),
routes = require('./lib/routes');
var _ = require('lodash'),
app = require('express')(),
siteService = require('./lib/sites'),
files = require('./lib/files'),
routes = require('./lib/routes'),
bootstrap = require('./lib/bootstrap'),
bluebird = require('bluebird'),
log = require('./lib/log'),
chalk = require('chalk');

/**
* Dims the log slightly.
* @param {string} msg
*/
function logLess(msg) {
log.info(chalk.dim(msg));
}

/**
* @returns {Promise}
*/
function bootstrapCurrentProject() {
return bootstrap('.').catch(function () {
logLess('No bootstrap found at root of project.');
});
}

/**
* @returns {Promise}
*/
function bootstrapComponents() {
var components = files.getComponents();

return bluebird.all(_.map(components, function (component) {
var componentPath = files.getComponentPath(component);
return bootstrap(componentPath).catch(function () {
logLess('No bootstrap found for ' + component);
});
}));
}

/**
* @returns {Promise}
*/
function bootstrapSites() {
var sites = siteService.sites();

return bluebird.all(_.map(sites, function (site) {
return bootstrap(site.dirPath, {uriPrefix: site.host + site.path}).catch(function () {
logLess('No bootstrap found for ' + site.slug);
});
}));
}

/**
* @returns {Promise}
*/
module.exports = function () {
return routes(app);
var router = routes(app);

//look for bootstraps in components
return bootstrapComponents().then(function () {
return bootstrapSites();
}).then(function () {
return bootstrapCurrentProject();
}).then(function () {
return router;
});
};

//services to outside
//services exposed to outside
module.exports.db = require('./lib/services/db');
module.exports.components = require('./lib/services/components');
module.exports.pages = require('./lib/services/pages');
90 changes: 71 additions & 19 deletions lib/bootstrap.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
'use strict';
var fs = require('fs'),
path = require('path'),
yaml = require('js-yaml'),
var path = require('path'),
files = require('./files'),
_ = require('lodash'),
bluebird = require('bluebird'),
components = require('./services/components'),
db = require('./services/db'),
log = require('./log'),
chalk = require('chalk');
log = require('./log');

/**
* Get yaml file as json
* Get yaml file as object
*
* @param {string} dir
* @returns {Object}
*/
function getConfig(dir) {
return yaml.safeLoad(fs.readFileSync(path.resolve(dir), 'utf8'));
dir = path.resolve(dir);

if (dir.indexOf('.', 2) > 0) {
//remove extension
dir = dir.substring(0, dir.indexOf('.', 2));
}

if (files.isDirectory(dir)) {
//default to bootstrap.yaml or bootstrap.yml
dir = path.join(dir, 'bootstrap');
}

return files.getYaml(dir);
}

/**
Expand Down Expand Up @@ -49,13 +60,21 @@ function saveWithInstances(dbPath, list, save) {
_.each(list, function (item, itemName) {
var obj = _.omit(item, 'instances');

promises.push(save(dbPath + itemName, obj));
if (_.isObject(item)) {
obj = _.omit(item, 'instances');

if (_.size(obj) > 0) {
promises.push(save(dbPath + itemName, obj));
}

if (item && item.instances) {
// load instances
_.each(item.instances, function (instance, instanceId) {
promises.push(save(dbPath + itemName + '/instances/' + instanceId, instance));
});
if (item && item.instances) {
// load instances
_.each(item.instances, function (instance, instanceId) {
if (_.size(instance) > 0) {
promises.push(save(dbPath + itemName + '/instances/' + instanceId, instance));
}
});
}
}
});

Expand Down Expand Up @@ -87,14 +106,27 @@ function saveObjects(dbPath, list, save) {
}));
}

function applyOptions(bootstrap, options) {
var prefix;

if (bootstrap.uris && options.uriPrefix) {
prefix = options.uriPrefix;
bootstrap.uris = _.transform(bootstrap.uris, function (uris, value, key) {
uris[prefix + key] = value;
});
}
}

/**
* Load items into db from yaml file
* @param {string} path
* @returns Promise
* Load items into db from config object
* @param {object} bootstrap
* @param {object} options
* @returns {Promise.<T>|*}
*/
module.exports = function (path) {
var componentsOps, pagesOps, urisOps, listsOps,
bootstrap = getConfig(path);
function load(bootstrap, options) {
var componentsOps, pagesOps, urisOps, listsOps;

applyOptions(bootstrap, options);

listsOps = saveObjects('/lists/', bootstrap.lists, getPutOperation);
urisOps = saveBase64Strings('/uris/', bootstrap.uris, getPutOperation);
Expand All @@ -118,4 +150,24 @@ module.exports = function (path) {

return db.batch(ops, { fillCache: false, sync: false });
});
}

/**
* Load items into db from yaml file
* @param {string} path
* @param {object} options
* @returns Promise
*/
module.exports = function (path, options) {
options = options || {};
var promise,
bootstrap = getConfig(path);

if (bootstrap) {
promise = load(bootstrap, options);
} else {
promise = Promise.reject(new Error('No bootstrap found at ' + path));
}

return promise;
};
51 changes: 43 additions & 8 deletions lib/bootstrap.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

var _ = require('lodash'),
fs = require('fs'),
files = require('./files'),
path = require('path'),
yaml = require('js-yaml'),
filename = __filename.split('/').pop().split('.').shift(),
Expand All @@ -17,14 +17,15 @@ describe(_.startCase(filename), function () {

before(function () {
this.timeout(400);
bootstrapFake = yaml.safeLoad(fs.readFileSync(path.resolve('./test/fixtures/config/bootstrap.yaml'), 'utf8'));
bootstrapFake = files.getYaml(path.resolve('./test/fixtures/config/bootstrap'));
});

beforeEach(function () {

sandbox = sinon.sandbox.create();
sandbox.stub(log);
sandbox.stub(db, 'formatBatchOperations').returns([]);

return db.clear();
});

Expand All @@ -37,23 +38,57 @@ describe(_.startCase(filename), function () {
return db.clear();
});

it('read basic components from bootstrap', function () {

it('missing bootstrap', function (done) {
bootstrap('./jfkdlsa').then(function () {
done('should throw');
}).catch(function () {
done();
});
});

it('reads from bootstrap', function () {
// this is doing IO, so give it more time.
this.slow(50);
this.timeout(400);
sandbox.stub(fs, 'readFileSync', '');
sandbox.stub(path, 'resolve', '');
sandbox.mock(yaml).expects('safeLoad').returns(bootstrapFake);

return bootstrap('./test/fixtures/config/bootstrap.yaml').then(function () {
return bootstrap('./test/fixtures/config/bootstrap').then(function () {
return db.get('/components/image/instances/0')
.then(JSON.parse)
.then(function (results) {
expect(results).to.deep.equal({
src: 'http://placekitten.com/400/600',
alt: 'adorable kittens'
});
sandbox.verify();
});
});
});

it('reads from bootstrap without bootstrap in path', function () {
// this is doing IO, so give it more time.
this.slow(50);
this.timeout(400);

return bootstrap('./test/fixtures/config');
});

it('reads from bootstrap with extension in path', function () {
// this is doing IO, so give it more time.
this.slow(50);
this.timeout(400);

return bootstrap('./test/fixtures/config/bootstrap.yaml');
});

it('reads from bootstrap with prefix', function () {
// this is doing IO, so give it more time.
this.slow(50);
this.timeout(400);

return bootstrap('./test/fixtures/config/bootstrap.yaml', {uriPrefix: 'test'}).then(function () {
return db.get('/uris/' + new Buffer('testa').toString('base64'))
.then(function (results) {
expect(results).to.equal('b');
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion lib/composer.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ function addParams(req, res) {
* @param {function} next
*/
function composer(req, res, next) {
var urlWithoutQuerystring = req.url.split('?').shift(),
var urlWithoutQuerystring = (req.baseUrl + req.url).split('?').shift(),
pageReference = '/uris/' + new Buffer(req.vhost.hostname + urlWithoutQuerystring).toString('base64');

addParams(req, res);
Expand Down
Loading

0 comments on commit 5b03af3

Please sign in to comment.