'use strict'; var express = require('express'); var _ = require('lodash'); var compress = require('compression'); var resourceParser = require('./resource-parser'); var DatabaseResourceRepository = require('./data'); var MemoryCacheResourceRepository = require('./memory'); var dbHost = '---'; var dbName = '---'; var dbUser = '---'; var dbPassword = '---'; var host = '---'; var resourceRepository = new MemoryCacheResourceRepository(new DatabaseResourceRepository(dbHost, dbName, dbUser, dbPassword)); var app = express(); app.disable('x-powered-by'); app.use(compress()); app.get('/:lib/releases', function(req, res) { var releases = resourceRepository.getAllReleasesByLib(req.params.lib); res.type('application/json'); res.send(JSON.stringify(releases, null, 2)); }); app.get('/list/:type', function(req, res) { var libs = resourceRepository.getAllReleasesByType(req.params.type); res.type('application/json'); res.send(JSON.stringify(libs, null, 2)); }); app.get(/\/([^/]+)\/(.+)\/*/, function(req, res) { var domain = req.params[0]; var resourcePath = req.params[1]; var resourceStrings = _.without(resourcePath.split('/'), ''); // Ignore empty parts var releaseRequests = resourceStrings.map(function(resourceString) { var match = resourceParser(resourceString); if (!match) { throw new Error('There is something wrong with the structure of this request. ' + 'Try requesting with the form \'http://abcdn.io/~-\'. ' + 'For example abcdn.io/bootstrap~3.0.0.js. ' + 'Remember though, both version and type are optional.'); } match.fullName = resourceString; return match; }); Promise.all(releaseRequests.map(function(releaseRequest) { var releases = resourceRepository.getReleases(releaseRequest); if (!releases) { res.status(404); throw new Error('ABCDN could not find a resource with the name \'' + releaseRequest.fullName + '\'. ' + 'Try requesting with the form \'http://abcdn.io/~-\'. ' + 'For example abcdn.io/bootstrap~3.0.0.js. ' + 'Remember though, both version and type are optional.'); } return releases; })).then(function(releases) { return _.flatten(releases); }).then(function(releases) { var thePackage = createPackage(releases, domain); res.setHeader('Cache-Control', 'public, max-age=2592000'); // 30 days res.type(thePackage.contentType); res.send(thePackage.content); }); }); resourceRepository.initialise().then(function() { var server = app.listen(8081, function() { var host = server.address().address; var port = server.address().port; console.log('ABCDN Resource Server listening at http://%s:%s', host, port); }); }); module.exports = app; function createPackage(releases, domain) { var groupedReleases = _.groupBy(releases, 'resourceType'); if (groupedReleases.js) { return createJSPackage(groupedReleases.js, groupedReleases.css, domain); } else { return createCSSPackage(groupedReleases.css); } } function createJSPackage(jsReleases, cssReleases, domain) { var releaseContents = _.map(jsReleases, 'content'); var thePackage = generateClientValidator(domain) + generateCssHeadAdder(cssReleases, domain) + releaseContents.join('\n'); return {contentType: 'text/javascript', content: thePackage}; } function createCSSPackage(cssReleases) { var releaseContents = _.map(cssReleases, 'content'); var thePackage = releaseContents.join('\n'); return {contentType: 'text/css', content: thePackage}; } function generateCssHeadAdder(cssReleases, domain) { if (!cssReleases) { return ''; } var cssUrl = '//' + host + '/' + domain + '/' + _.map(cssReleases, function(release) { return release.fullName + '.css' }).join('/'); function cssHeadAdder(cssUrl) { var headHTML = document.getElementsByTagName('head')[0].innerHTML; headHTML += ''; document.getElementsByTagName('head')[0].innerHTML = headHTML; } return '(' + cssHeadAdder.toString() + ')(\'' + cssUrl + '\');\n'; } function generateClientValidator(domain) { function validator(domain) { if (window.location.host != domain) { alert('This package from ABCDN.io is permitted to be used on ' + domain + ' only. But don\'t worry, you too can use ABCDN.io for free like this: http://www.abcdn.io/mywebsite.com/jquery/angular/bootstrap'); } } return '(' + validator.toString() + ')(\'' + domain + '\');\n'; }