UNPKG

pp-parachute

Version:
248 lines (221 loc) 8.7 kB
var Errors = require('././errors'); var Promise = require('bluebird'); var UrlPatternPairing = require('./url_env_pair'); var explode = require('././explosives'); var fs = require('fs'); var path = require('path'); var config = require('./config'); var toArray = require('../util/array').toArray; var promisify = require('../util/promisify'); var applicationInstances = {}; var servedUrlPatterns = []; var currentEnvironment = null; var matchedUrl = null; var initialize = function () { var manifest = config.getApplications(); var applicationNames = Object.keys(manifest); for (var i = 0; i < applicationNames.length; i++) { var applicationName = applicationNames[i]; var applicationPath = manifest[applicationName]; loadApplication(applicationName, applicationPath); } }; var getApplication = function (applicationName) { return applicationInstances[applicationName]; }; var loadApplication = function (applicationName, applicationPath) { if (!fs.existsSync(applicationPath)) { return explode(Errors.ApplicationMissing, applicationName, applicationPath); } if (applicationInstances[applicationName]) { return; //todo maybe explode nicely to notify user application was not loaded? } try { var application = require(applicationPath); application.getEnvironments().forEach(function (env) { mapEnvironmentUrlPatterns(env); }); applicationInstances[applicationName] = application; } catch (e) { return explode(e); } }; var hasExactUrl = function(url) { if(!currentEnvironment) return false; var servedUrls = currentEnvironment.getServedUrls(); for(var i = 0; i < servedUrls.length; i++) { if(servedUrls[i] === url || servedUrls[i] + '/' === url) return true; } return false; }; var mapEnvironmentUrlPatterns = function (environment) { environment.getServedUrls().forEach(function (url) { servedUrlPatterns.push(new UrlPatternPairing(url, environment)); }); }; var setEnvironmentForUrl = function (url) { currentEnvironment = null; matchedUrl = null; for (var i = 0; i < servedUrlPatterns.length; i++) { var patternPair = servedUrlPatterns[i]; if (patternPair.match(url)) { matchedUrl = patternPair.pattern; return (currentEnvironment = patternPair.environment); } } return currentEnvironment; }; var getCurrentEnvironment = function () { return currentEnvironment; }; var getAssetRoot = function () { return currentEnvironment && currentEnvironment.getAssetRoot(); }; var getViewData = function () { if (!currentEnvironment) return null; var viewFile = currentEnvironment.getViewFile(); var engine = path.extname(viewFile).substring(1); return { viewFile: path.basename(viewFile, '.' + engine), viewDirectory: path.dirname(viewFile), viewEngine: engine } }; var getMatchedUrl = function () { return matchedUrl; }; var renameApplication = function (appName, newName) { var application = applicationInstances[appName]; if (!application) return explode(Errors.ApplicationMissingByName, appName); application.name = newName; config.renameApplication(appName, newName); }; var addApplication = function (applicationPath) { if (!fs.existsSync(applicationPath)) { return explode(Errors.NoApplicationAtPath, applicationPath); } var appAtPath = toArray(applicationInstances).filter(function (app) { return app.absolutePath + '/parachute.js' === applicationPath; }); if (appAtPath.length !== 0) { return console.log('Application already exists -- no problems here'); } try { var application = require(applicationPath); if (applicationInstances[application.name]) { var name = application.name; var abspath = applicationInstances[application.name].absolutePath; return explode(Errors.ApplicationAlreadyExists, name, abspath); } application.getEnvironments().forEach(function (env) { mapEnvironmentUrlPatterns(env); }); applicationInstances[application.name] = application; } catch (e) { return explode(e); } config.addApplication(application.name, applicationPath); }; var removeApplication = function (appName) { //go through all envs and kill them if they are part of removed application var removedApplication = applicationInstances[appName]; if (!removedApplication) return explode(); servedUrlPatterns = servedUrlPatterns.filter(function (patternPair) { return patternPair.environment.application !== removedApplication; }); removedApplication.shutdown(); config.removeApplication(appName); }; var buildApplication = function (appName, envName) { var application = applicationInstances[appName]; if (!application) return explode(Errors.ApplicationMissingByName, appName); var env = application.getEnvironment(envName); if (!env) return explode(Errors.EnvironmentMissingByName, appName, envName); return env.build(); }; var watchApplication = function (appName, envName) { var application = applicationInstances[appName]; if (!application) return explode(Errors.ApplicationMissingByName, appName); var env = application.getEnvironment(envName); if (!env) return explode(Errors.EnvironmentMissing, appName, envName); return env.watch(); }; var buildForServing = function (req, res, server) { var originalBuildPromise = currentEnvironment.buildPromise; var watchPromise = currentEnvironment.watch(); if (originalBuildPromise !== watchPromise) { var passed; return watchPromise.then(function (_passed) { passed = _passed; var passedHandler = currentEnvironment.getServedBuildSucceededHandler(); var failedHandler = currentEnvironment.getServedBuildFailedHandler(); if (passed && passedHandler) { return promisify(passedHandler(currentEnvironment, req, res, server)); } else if (!passed && failedHandler) { return promisify(failedHandler(currentEnvironment, req, res, server)); } return Promise.resolve(); }).then(function () { var completedHandler = currentEnvironment.getServedBuildCompletedHandler(); if (!res.headersSent && completedHandler) { return promisify(completedHandler(currentEnvironment, passed, req, res, server)); } return Promise.resolve(passed); }); } else { return watchPromise; } }; var serveCurrentEnvironment = function (req, res, next, server) { if (!currentEnvironment) { return Promise.reject("Current Environment is not defined"); } if (currentEnvironment.buildPromise === null) { var initializedHandler = currentEnvironment.getServedBuildInitializedHandler(); if (initializedHandler) { var initialBuildPromise = promisify(initializedHandler(currentEnvironment, req, server)); return initialBuildPromise(currentEnvironment, req, server).finally(function () { return buildForServing(req, res, server); }); } } return buildForServing(req, res, server); }; var watchCurrentEnvironment = function () { return currentEnvironment.watch(); }; //lists all known applications, their paths and their environments var listApplications = function () { var appNames = Object.keys(applicationInstances); for (var i = 0; i < appNames.length; i++) { var app = applicationInstances[appNames[i]]; console.log(app.name, app.absolutePath, Object.keys(app.environments)); } }; //only used for testing var clear = function () { applicationInstances = {}; servedUrlPatterns = []; currentEnvironment = null; matchedUrl = null; }; initialize(); module.exports = { loadApplication: loadApplication, getApplication: getApplication, setEnvironmentForUrl: setEnvironmentForUrl, getCurrentEnvironment: getCurrentEnvironment, getAssetRoot: getAssetRoot, getViewData: getViewData, getMatchedUrl: getMatchedUrl, buildApplication: buildApplication, watchApplication: watchApplication, watchCurrentEnvironment: watchCurrentEnvironment, serveCurrentEnvironment: serveCurrentEnvironment, listApplications: listApplications, addApplication: addApplication, removeApplication: removeApplication, renameApplication: renameApplication, clear: clear, hasExactUrl: hasExactUrl };