{"version":3,"sources":["jsdelivr-header.js","/npm/@blacklight-cms/core@0.8.7/index.js"],"names":[],"mappings":"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","file":"/npm/@blacklight-cms/core@0.8.7/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@blacklight-cms/core@0.8.7/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","var addHelpers=require(\"./lib/blacklight-helpers\");\nvar _=require(\"lodash\");\nvar _path=require(\"path\");\nvar fs=require(\"fs\");\nvar express=require(\"express\");\nvar compression = require('compression');\nvar bodyParser = require('body-parser');\nvar cookieParser = require('cookie-parser')\nvar http=require(\"http\");\nvar SlingConnector=require(\"@entropy/sling-connector\");\nvar c=require(\"./lib/colors\");\nvar sanitize = require(\"./lib/sanitize\");\nconst { EventEmitter } = require(\"events\");\n\n\n\n// TODO: USe node domains or other mechanism for better top-level exception handling.\n// console.log(\"blacklight-core: index.js:  you should set up an exception-catching domain here?\")\n\nmodule.exports=function(options){\n\n\tvar hostLookup={}, portLookup={}, siteLookup={};\n\tvar trustForwardedHostHeader, globalDefaultPort;\n\n\tvar blacklight = global.bl = {SlingConnector, events: new EventEmitter()};\n\n\tblacklight.sanitize = sanitize;\n\tblacklight.logger = _.get(options, \"logger\", require(\"./lib/logger\"));\n\n\toptions=options||{};\n\toptions.appRoot = options.appRoot || process.env.BLACKLIGHT_ROOT;\n\tif(!options.appRoot){throw new Error(\"options.appRoot must be set to the home directory of your blacklight installation.\");}\n\toptions.appRoot = normalizePath(options.appRoot);\n\n\tvar initStatus={}, initSteps=[\"configure\",\"loadModules\",\"addRoutes\",\"buildVhostLookups\",\"listen\"];\n\tvar pluginCategories=[\"emailError\", \"logger\", \"blacklightProxy\", \"staticTranslation\",\"imgOptProcessor\",\"imgOptRenditionsBacking\",\"imgOptOriginalsBacking\", \"secretsManager\"];\n\n\taddHelpers(blacklight, options);\n\tblacklight.plugins={};\n\n\n\tprocess.env.NODE_CONFIG_DIR = options.appRoot + \"/config\";\n\tvar config = blacklight.config = require(\"config\");\n\n\tconst registryLookup = (site) => {\n\t\treturn _.get(blacklight.sites, [site, 'registry']);\n\t}; \n\n\n\n\t/**********************************************************************************/\n\tblacklight.run = async function(){\n\t\tawait blacklight.listen();\n\t\tglobal.bl.events.emit(\"started\");\n\t}\n\n\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tblacklight.configure = async function(){\n\t\tif(initStatus.configure){return;}\n\t\tawait initializeTo(\"configure\");\n\t\tvar log = global.bl.logger.get(\"blacklight.config\");\n\n\t\tvar siteRoot = _path.join(options.appRoot,\"blacklight_modules\");\n\t\tvar sites = fs.readdirSync(siteRoot);\n\t\t//skip hidden directories and files\n\t\tsites = _.filter(sites, function(site){\n\t\t\tif(site[0] !== '.' && fs.statSync(_path.join(siteRoot, site)).isDirectory()){\n\t\t\t\treturn true; \n\t\t\t}else{\n\t\t\t\tlog.warning(`Warning: Skipping file or hidden directory : ${site}`);\n\t\t\t\treturn false; \n\t\t\t}\n\t\t\t \n\t\t});\n\t\tblacklight.sites={};\n\t\tvar defaultSite = blacklight.defaultSite = _.get(config,\"environment.defaultSite\");\n\n\n\t\tif(!defaultSite){\n\n\t\t\tif(sites.length){\n\t\t\t\tif(!defaultSite){\n\t\t\t\t\t// Note: For a few reasons, it is preferrable NOT to infer defaultSite.  If you feel it is a sticking point for ease of use, then have the value auto-written by the bl initializer.  Don't question this conclusion, just do it.\n\t\t\t\t\tlog.error(\"A multi-site Blacklight installation requires 'environment.defaultSite' to be specified in your local configuration file:\\n\", _path.join(siteRoot,\"../config/local.json\"))\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif(sites.length>2){\n\t\t\t\t\tlog.error(\"You must set 'environment.defaultSite' in your local configuration file:\\n\", _path.join(siteRoot,\"../config/local.json\"))\n\t\t\t\t}else{\n\t\t\t\t\tlog.error(\"You do not appear to have any sites installed in Blacklight.\\nUse `\" + c.green(\"bl site install\") + c.white(\"` or `\") + c.green(\"bl site create\") + c.white(\"` to correct this issue.\"))\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\n\t\tsites.forEach((site)=>{\n\n\t\t\t\n\t\t\tvar siteConfigPath = _path.join(siteRoot, site, \"site/apps/config.json\");\n\t\t\tvar siteModulePath = _path.join(siteRoot, site, \"site/apps/site.js\"), siteModule;\n\n\t\t\ttry{\n\t\t\t\tvar siteConf=require(siteConfigPath);\n\t\t\t\tblacklight.sites[site]={};\n\t\t\t\tsiteConf.environment = siteConf.environment || {};\n\t\t\t\tsiteConf.environment = config.util.extendDeep(siteConf.environment, config.environment);\n\t\t\t\tsiteConf.configPath = siteConfigPath;\n\t\t\t\tconfig.util.setModuleDefaults(site, siteConf);\n\n\t\t\t}catch(err){\n\t\t\t\tlog.error(\"ERROR: Problem loading configuration file for site '\" + site + \"' at:\", siteConfigPath, err);\n\t\t\t\treturn;\n\t\t\t\t// process.exit(1);\n\t\t\t}\n\n\t\t\ttry{\n\t\t\t\tsiteModule = require(siteModulePath);\n\t\t\t}catch(err){\n\t\t\t\t/// TODO: this should fail differently for a syntax error, vs just not being present on disk.  Missing file is OK.  Broken file is not.\n\t\t\t\tlog.error(\"Problem loading site.js for '\" + site + \"'\", siteModulePath, err);\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\tblacklight.sites[site].helpers = siteModule || {};\n\t\t});\n\n\t\tblacklight.appRoot = config.appRoot = options.appRoot;\n\t\tconfig.environment = _.get(config,[defaultSite,\"environment\"], config.environment);\n\n\t\tvar logPlugin = global.bl.logger.get(\"blacklight-core\");\n\n\t\tfunction configurePlugins(site){\n\t\t\tvar configHelper = blacklight.pluginConfigHelper(site);\n\n\t\t\tvar sitePlugins = _.get(blacklight.sites, [site, \"helpers\", \"plugins\"]);\n\t\t\tlet pluginCb = _.get(blacklight.sites, [site, \"helpers\", \"onPluginLoaded\"]);\n\t\t\tif(sitePlugins){\n\t\t\t\tpluginCategories.forEach((category)=>{\n\t\t\t\t\tvar pluginFactory=sitePlugins[category];\n\t\t\t\t\tif(pluginFactory){\n\t\t\t\t\t\tif(!_.isFunction(pluginFactory)){throw(`Plugin '${category}' is not a function.`)}\n\t\t\t\t\t\tvar configuredPlugin=pluginFactory(config, configHelper);\n\t\t\t\t\t\tif(site===blacklight.defaultSite){\n\t\t\t\t\t\t\tblacklight[category]=configuredPlugin;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// logPlugin.debug(\"Configuring plugin '\" + category + \"' for site '\" + site + \"'\");\n\t\t\t\t\t\t_.set(blacklight,[category,\"sites\",site], configuredPlugin);\n\n\t\t\t\t\t\tif(pluginCb){\n\t\t\t\t\t\t\tpluginCb(category, configuredPlugin);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconfigurePlugins(defaultSite);\n\t\tsites.forEach((site)=>{\n\t\t\tif(site!==defaultSite){\n\t\t\t\tconfigurePlugins(site);\n\t\t\t}\n\t\t});\n\n\t\tvar defaultAppsMount = normalizePath(_.get(config, defaultSite + \".appsMount\"));\n\t\tvar defaultPublicMount = normalizePath(_.get(config, defaultSite + \".publicMount\"));\n\t\tblacklight.appsMount=defaultAppsMount;\n\t\tblacklight.publicMount=defaultPublicMount;\n\n\t\t[\"appsMount\",\"publicMount\"].forEach((setting)=>{\n\t\t\tif(!_.get(config, [defaultSite,setting])){\n\t\t\t\tvar msg=`Default site (${defaultSite}) - config.json must include '` + setting + \"'\";\n\t\t\t\tlog.error(msg)\n\t\t\t\tthrow new Error(msg);\n\t\t\t}\n\t\t});\n\n\t\tsites.forEach((site)=>{\n\t\t\t//  Normalize appsMount, publicMount, baseUri values\n\t\t\tvar siteConfig = config[site];\n\t\t\tvar appProperty = site + \".appsMount\";\n\t\t\tvar pubProperty = site + \".publicMount\";\n\n\t\t\t_.set(config, appProperty, normalizePath(_.get(config,appProperty)), defaultAppsMount);\n\t\t\t_.set(config, pubProperty, normalizePath(_.get(config,pubProperty)), defaultPublicMount);\n\n\t\t\tif(siteConfig && siteConfig.slingBasePath){siteConfig.slingBasePath = (\"/\" + _.trim(siteConfig.slingBasePath,\"/\") + \"/\");}\n\n\n\t\t\tvar blSlingConfig = _.get(blacklight.sites, [\"blacklight\",\"helpers\",\"slingConfig\"],({site})=>{return{};})(siteConfig);\n\t\t\tvar siteSlingConfig = _.get(blacklight.sites, [site,\"helpers\",\"slingConfig\"],({site})=>{return{};})(siteConfig);\n\n\t\t\t// combine \"blacklight.site\" slingConfig with each site-specific slingConfig.\n\t\t\tvar helperSlingConfigs = _.defaults(blSlingConfig, siteSlingConfig);\n\t\t\tif(blSlingConfig.preprocessors && siteSlingConfig.preprocessors){\n\t\t\t\thelperSlingConfigs.preprocessors = blSlingConfig.preprocessors.concat(siteSlingConfig.preprocessors);\n\t\t\t}\n\n\t\t\tvar slings = _.get(config, site + \".modes\");\n\t\t\t_.each(slings,(host,key)=>{\n\t\t\t\tif(!host){_.unset(config[site],[\"modes\",key]);return;}\n\t\t\t\tvar sling=host.sling;\n\t\t\t\tif(!sling.baseUri){throw new Error(\"Missing baseUri in sling configuration: \" + site + \".modes.\" + key + \".sling\");}\n\t\t\t\tsling.baseUri = sling.baseUri.replace(/\\/$/,\"\");\n\t\t\t\thost.sling = _.defaults(host.sling, helperSlingConfigs, {mode:key})  // take result of merging bl.site's, and the current site's, configs (from the site.js \"helper\" configs) and merge that result into config.json's sling config values\n\t\t\t})\n\n\t\t});\n\n\t\tconfig.get(\"environment\"); // Invoke a \"get\" call, just to make the config immutable.\n\n\t\tglobal.bl.processScripts.watchForChanges();\n\t}\n\n\n\n\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tblacklight.loadModules = async function(){\n\t\tawait initializeTo(\"loadModules\");\n\n\t\t// /// Instantiate sling connectors for all sites\n\t\t// _.each(blacklight.sites, (siteObject, site)=>{\n\t\t// \tvar slingConfigs = _.get(blacklight.config[site], \"modes\"), defaultConfig;\n\t\t// \tif(slingConfigs){\n\t\t// \t\tvar defaultConfigBuilder = _.get(siteObject, \"helpers.slingConfig\");\n\t\t// \t\tif(defaultConfigBuilder){\n\t\t// \t\t\tdefaultConfig=defaultConfigBuilder()\n\n\t\t// \t\t}\n\t\t// \t}\n\t\t// });\n\n\t\tblacklight.modules = blacklight.moduleLoader({siteConnections: blacklight.sites, defaultSite: blacklight.defaultSite, registryLookup});\n\t\tglobal.bl.events.emit(\"loaded.modules\");\n\t\tglobal.bl.queues = await require(\"./lib/queues\")(blacklight.modules.queues);\n\t\tglobal.bl.events.emit(\"loaded.queues\");\n\t}\n\n\n\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tblacklight.addRoutes = async function(){\n\t\tawait initializeTo(\"addRoutes\");\n\t\tvar log=global.bl.logger.get(\"blacklight-core.addRoutes\");\n\t\tvar requestPreprocessors=[];\n\n\t\t// forEach site that actually has vhost definitions, create an app, and attach it to the blacklight.sites object\n\n\t\t// TODO: each site definition now needs to include a \"primaryContentPath\" (/content/fourseasons)  and \"hostRegex\"\n\t\t\t// (these can be auto-generated by inference, but also overridden by user)\n\n\t\tfor(const site of Object.keys(blacklight.sites)){\n\t\t\tconst siteObject = blacklight.sites[site];\n\t\t\tvar siteConfig = _.get(config, site);\n\t\t\tvar siteEnvironment = _.get(config, site + \".environment\");\n\t\t\tvar siteHelpers = _.get(siteObject, \"helpers\", {});\n\t\t\tvar modes = _.get(siteConfig, \"modes\");\n\t\t\tvar proxyRegex = new RegExp(\"^\" + siteConfig.appsMount + \"blacklight/edit/proxy/\");\n\t\t\tif(modes){\n\n\t\t\t\tvar app = express();\n\t\t\t\tapp.disable('x-powered-by');\n\n\n\t\t\t\tvar blacklightProxy = siteEnvironment.blacklightProxy;\n\n\n\t\t\t\tif(blacklightProxy && !blacklightProxy.disabled){\n\t\t\t\t\tconsole.log(\"Launching site '\" + site + \"' via blacklight proxy to\", siteConfig.environment.blacklightProxy);\n\t\t\t\t\tapp.all( siteConfig.appsMount + \"*\", blacklightProxy.appsProxy());\n\t\t\t\t\tapp.all( siteConfig.publicMount + \"img-opt/*\", blacklightProxy.appsProxy());\n\t\t\t\t\t// TODO: rooted routes are not currently added into bl-proxy.  how would you do that?\n\n\t\t\t\t\tvar slingBaseRegex = \"^/content/\" + site + \"/\";\n\t\t\t\t\tif(siteConfig.slingBasePath){slingBaseRegex=\"^\" + siteConfig.slingBasePath;}\n\n\t\t\t\t\trequestPreprocessors = [\n\t\t\t\t\t\t{path: slingBaseRegex, proxy: blacklightProxy.contentProxy}\n\t\t\t\t\t];\n\n\t\t\t\t}else{\n\t\t\t\t\t\n\t\t\t\t\tif(siteHelpers.authHandlers){\n\t\t\t\t\t\t_.each(siteHelpers.authHandlers, (handler)=>{\n\t\t\t\t\t\t\tapp.all(handler.path, \n\t\t\t\t\t\t\t\thandler.parseCookies ? cookieParser() : (req,res,next)=>{next()},\n\t\t\t\t\t\t\t\t(req,res, next)=>{\n\t\t\t\t\t\t\t\t\t//handlers can return a Promise if async is needed\n\t\t\t\t\t\t\t\t\tlet handlerRet = handler.handle(req);\n\t\t\t\t\t\t\t\t\tif(handlerRet && _.isFunction(handlerRet.then)){\n\t\t\t\t\t\t\t\t\t\thandlerRet.then(next, next).catch(e => {\n\t\t\t\t\t\t\t\t\t\t\tlog.error(`Error with ${site} authHandlers`, e);\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\t\tnext(); \n\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\tapp.use(siteConfig.publicMount + \"img-opt/\", \n\t\t\t\t\t\tblacklight.imgOpt(siteEnvironment.imageOptimizer, \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprocessor: _.get(blacklight, [\"imgOptProcessor\",\"sites\",site]),\n\t\t\t\t\t\t\t\trenditionsBacking: _.get(blacklight, [\"imgOptRenditionsBacking\",\"sites\",site]), \n\t\t\t\t\t\t\t\toriginalsBacking: _.get(blacklight, [\"imgOptOriginalsBacking\",\"sites\",site])\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\n\t\t\t\t\t// GZIP compression, applies to all subsequent middleware responses with appropriate content-types\n\t\t\t\t\tapp.use(compression({threshold: 0}));\n\n\n\t\t\t\t\t// All module \"rooted-routes\"  mounted here\n\t\t\t\t\tapp.all(\"*\",\n\t\t\t\t\t\tbodyParser.json(),\n\t\t\t\t\t\tfunction(req,res,next){\n\t\t\t\t\t\t\tif(req.method===\"POST\" && !proxyRegex.test(req.url)){\n\t\t\t\t\t\t\t\tbodyParser.urlencoded({extended: true})(req, res, next);\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// TODO: add authenticator here?\n\t\t\t\t\t\tblacklight.modules.rootedRouter);\n\n\n\t\t\t\t\t// All site/project-level routers mounted here\n\t\t\t\t\tapp.use(siteConfig.appsMount,  blacklight.modules.router);\n\n\n\t\t\t\t\t// var requestPreprocessors = _.get(blacklight, \"sites.blacklight.helpers.preprocessors\", ()=>{return []})();\n\n\n\t\t\t\t\tif(siteHelpers.preprocessors){\n\t\t\t\t\t\trequestPreprocessors = requestPreprocessors.concat(siteHelpers.preprocessors({modules: blacklight.modules}));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\t// TODO: per-site favicon customization\n\n\t\t\t\t// Static file handler (i.e /public files)\n\t\t\t\tvar staticHandler = express.static(options.appRoot + \"/public/\", {etag: false});\n\n\t\t\t\tvar cacheBuster=function(req,res,next){\n\t\t\t\t\tvar cacheBuster=req.path.match(/.*(\\.\\d{4,})\\.(js|css)$/);\n\t\t\t\t\tif(cacheBuster){\n\t\t\t\t\t\tvar parts=req.url.split(\"?\");\n\t\t\t\t\t\tparts[0] = parts[0].replace(cacheBuster[1], \"\");\n\t\t\t\t\t\treq.url=parts.join(\"?\");\n\t\t\t\t\t}\n\t\t\t\t\tnext();\n\t\t\t\t}\n\n\t\t\t\tif(siteHelpers.assetHandler){\n\t\t\t\t\tstaticHandler = siteHelpers.assetHandler(staticHandler);\n\t\t\t\t}\n\n\t\t\t\t// console.log(\"Public mount for '\" + site + \"'\", siteConfig.publicMount);\n\n\t\t\t\tapp.use(siteConfig.publicMount,\n\n\t\t\t\t\tcacheBuster,\n\n\t\t\t\t\t(req,res,next)=>{\n\t\t\t\t\t\tif(req.skipStatic){\n\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tstaticHandler(req,res,next);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\t\tfunction(req,res,next){\n\t\t\t\t\t\tif(req.skipStatic){\n\t\t\t\t\t\t\tnext();\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tres.status(404).send(\"404 error: Static asset not found\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\n\n\t\t\t\tvar wellKnownStaticHandler = express.static(options.appRoot + \"/public/\" + site + \"/site/.well-known/\", {etag: false});\n\t\t\t\tapp.use(\"/.well-known/\",\n\t\t\t\t\twellKnownStaticHandler,\n\t\t\t\t\tfunction(req,res,next){\n\t\t\t\t\t\tres.status(404).send(\"404 error: Static asset not found\");\n\t\t\t\t\t}\n\t\t\t\t);\n\n\n\t\t\t\tvar componentPaths = blacklight.buildComponentRoots(siteConfig.componentRoots);\n\t\t\t\tvar env = siteConfig.environment || {};\n\t\t\t\tvar devMode = env.devMode;\n\t\t\t\tvar staticTranslation = _.get(blacklight,[\"staticTranslation\",\"sites\",site], ()=>{return \"ERROR: Translate plugin not installed\";});\n\n\n\t\t\t\tconst registry = blacklight.componentTypes.createRegistry({\n\t\t\t\t\tcomponentPaths, \n\t\t\t\t\tcomponentCacheDisable: env.componentCacheDisable,  \n\t\t\t\t\tcomponentCacheClearOnChange: firstDef(env.componentCacheClearOnChange, devMode), \n\t\t\t\t\tpostProcessOptions: {minifyHTML: firstDef(env.minifyHTML, !devMode), beautifyHTML: firstDef(devMode, true)},\n\t\t\t\t\tpublicRoot: _path.resolve(options.appRoot, \"public\"),\n\t\t\t\t\temailError: blacklight.emailError ? blacklight.emailError : ()=>{},\n\t\t\t\t\ttranslationMethod: staticTranslation\n\t\t\t\t});\n\n\t\t\t\tvar blacklightHandler= await blacklight.express({\n\t\t\t\t\tregistry,\n\t\t\t\t\tutilities: blacklight.modules.modelHelpers,\n\t\t\t\t\tlanguage: siteConfig.language,\n\t\t\t\t\tenvironmentName: env.environmentName,\n\t\t\t\t\trequestPreprocessors: requestPreprocessors,\n\t\t\t\t\tskipModelProcessors: env.blacklightProxy?true:false\n\t\t\t\t})\n\n\t\t\t\tsiteObject.registry = registry;\n\n\t\t\t\t// Configure and inject Blacklight handler\n\t\t\t\tapp.use(\n\t\t\t\t\t// (req,res,next)=>{console.log(\"Looking up with Blacklight:\", req.url);next();},\n\t\t\t\t\tblacklightHandler\n\t\t\t\t);\n\n\t\t\t\t// error handler\n\t\t\t\tapp.use(function (err, req, res, next) {\n\t\t\t\t\tif (res.headersSent) {\n\t\t\t\t\t\treturn next(err)\n\t\t\t\t\t}\n\n\t\t\t\t\tconsole.error(\"Express error\", err);\n\t\t\t\t\tres.status(500).send(\"Something went wrong\");\n\t\t\t\t});\n\t  \n\t\t\t\tsiteObject.app = app;\n\t\t\t}\n\t\t}\n\n\n\t\tfunction firstDef(value, fallback){\n\t\t\tif(typeof(value)===\"undefined\"){\n\t\t\t\treturn fallback;\n\t\t\t}else{\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\n\t}\n\n\n\n\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tblacklight.buildVhostLookups = async function(){\n\t\tawait initializeTo(\"buildVhostLookups\");\n\n\t\t// build lookup tables\n\n\t\t// Need site + sling-source. So go through the following until you have both:\n\t\t// \thostname\n\t\t// \tport\n\t\t// \tx-sling-source  (including dotted site.mode format)\n\n\n\t\t// HOST dictionary key:  can either be  \"*.something.specific\"  or  \"something.exactly.specific\"\n\t\t// Examples:  \"www.my-site.com\", *.my-site.com\"  \"*.ms.local\"  [\"*.stage.my-site.com\",\"www.my-site.com\"]\n\n\n\n\t\t_.each(blacklight.sites, (siteObject, site)=>{\n\n\t\t\tvar siteApp=siteObject.app;\n\t\t\tif(!siteApp){return;}\n\t\t\tvar siteConfig = config[site];\n\t\t\tvar defaultHostname = siteConfig.hostname;\n\t\t\tvar baseSettings = {site: site, app: siteApp, siteConfig: siteConfig};\n\t\t\tvar isDefaultSite  =  (site === blacklight.defaultSite);\n\t\t\tvar DEFAULT_PORT = 4400;\n\t\t\tglobal.bl.vhosts={};\n\n\n\t\t\tif(defaultHostname && !_.isArray(defaultHostname)){defaultHostname = [defaultHostname];}\n\n\n\t\t\tfunction addVhost(hostname, port, settings){\n\t\t\t\tvar vhost=hostname + \":\" + port;\n\t\t\t\tvar scId = settings.site + \".\" + settings.mode;\n\n\n\t\t\t\tif(hostLookup[vhost]){\n\t\t\t\t\tconsole.log(c.red(\"\\n\\nERROR: \"), c.yellow(\"Duplicate vhost entry for site:\"), c.white(scId),\n\t\t\t\t\t\tc.yellow(\"\\n\\tPlease make sure you have a unique hostname and/or port specified in the BL configuration for:\"),\n\t\t\t\t\t\tc.white(\"\\n\\t\" + settings.site + \".modes.\" + settings.mode + \"\\n\\n\") );\n\t\t\t\t\tthrow new Error(\"Configuration problem: duplicate vhost entry '\" + vhost + \"' for [\" + scId + \"]\")\n\t\t\t\t}\n\t\t\t\thostLookup[vhost] = settings;\n\t\t\t}\n\n\t\t\t_.each(siteConfig.modes, (host, mode)=>{\n\t\t\t\tvar currentVhost = _.assign({mode:mode, sling: new SlingConnector(host.sling)}, baseSettings);\n\t\t\t\tcurrentVhost.reqBl={sling: currentVhost.sling, mode: mode, site: site, config: siteConfig, plugins:{}};\n\t\t\t\t_.each(pluginCategories, (pluginId)=>{\n\t\t\t\t\tif(blacklight[pluginId]){\n\t\t\t\t\t\tcurrentVhost.reqBl.plugins[pluginId]=_.get(blacklight,[pluginId, \"sites\", site], blacklight[pluginId]);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\n\t\t\t\tsiteLookup[site + \".\" + mode] = currentVhost;\n\t\t\t\tvar port = host.port || siteConfig.port || DEFAULT_PORT;\n\n\t\t\t\tvar scSpecificHostname=host.hostname;\n\t\t\t\tif(scSpecificHostname){\n\t\t\t\t\tif(!_.isArray(scSpecificHostname)){scSpecificHostname = [scSpecificHostname];}\n\t\t\t\t\tscSpecificHostname.forEach((hostname)=>{\n\t\t\t\t\t\taddVhost(hostname, port, currentVhost);\n\t\t\t\t\t});\n\t\t\t\t}else{\n\t\t\t\t\tif(defaultHostname){\n\t\t\t\t\t\tfor(var i=0; i<defaultHostname.length; i++){\n\t\t\t\t\t\t\tif(mode===\"publish\"){\n\t\t\t\t\t\t\t\taddVhost(defaultHostname[i], port, currentVhost);\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\tvar parts=defaultHostname[i].match(/(^www\\.|^\\*\\.)(.*)/);     // This is a non-publish SC without a hostname entry, so auto-generate a name\n\t\t\t\t\t\t\t\tif(parts){\n\t\t\t\t\t\t\t\t\taddVhost(mode + \".\" + parts[2], port, currentVhost);\n\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\taddVhost(mode + \".\" + defaultHostname[i], port, currentVhost);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\t// no specific or default hostname, and if there is no port specified up the port number by 1.\n\t\t\t\t\t\tif(mode===\"publish\" && !host.port){port=port+1;}\n\t\t\t\t\t\taddVhost(\"*\", port, currentVhost);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar existingDefault = portLookup[port];\n\t\t\t\tif(existingDefault){\n\t\t\t\t\tif((isDefaultSite || existingDefault.site === site) && (mode===\"publish\")){\n\t\t\t\t\t\tportLookup[port] = currentVhost;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tportLookup[port] = currentVhost;\n\t\t\t\t}\n\n\t\t\t\tif(isDefaultSite && mode === \"publish\"){\n\t\t\t\t\tglobalDefaultPort = port;\n\t\t\t\t}\n\n\t\t\t\tglobal.bl.vhosts[`${host}.${mode}`] = currentVhost;\n\t\t\t});\n\n\n\t\t\t_.each(portLookup, (portApp, port)=>{\n\t\t\t\tvar vhost=\"*:\"+port;\n\t\t\t\thostLookup[vhost]=null;\n\t\t\t\taddVhost(\"*\", port, portApp);\n\t\t\t})\n\n\t\t\t// iterate over all hostLookup entries, and compare with all siteLookup entries.\n\t\t\t// And then make sure all siteLookup entries have a vhost (so no sites/modes are orphaned)\n\n\t\t\tvar foundAtLeastOneVhost = false;\n\t\t\tconsole.log();\n\t\t\t_.each(hostLookup,(hostApp, host)=>{\n\t\t\t\tconsole.log(c.magenta(\"VHOST:\"), c.blue(\"Listening for\"), c.white(\"[\" + hostApp.site + \".\" + hostApp.mode + \"]\"), c.blue(\"on\"), c.white(\"[\" + host + \"]\"));\n\t\t\t\tfoundAtLeastOneVhost=true;\n\t\t\t})\n\n\t\t\tif(!foundAtLeastOneVhost){\n\t\t\t\tthrow new Error(\"No vhosts found.  Please configure at least on vhost by adding a 'hostname' entry to the '\" + blacklight.defaultSite + \"' config.json file.\")\n\t\t\t}\n\n\t\t\t_.each(siteLookup,(siteApp, site)=>{\n\t\t\t\tvar found=false;\n\t\t\t\t_.each(hostLookup,(hostApp, host)=>{\n\t\t\t\t\tif(siteApp===hostApp){\n\t\t\t\t\t\tfound=true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tif(!found){\n\t\t\t\t\tvar msg=\"No route to virtual host: \"\n\t\t\t\t\tconsole.log(c.magenta(\"\\nWARNING:\"), c.blue(msg), c.white(site) + \"\\n\", c.blue(\"        To connect, add a unique hostname and/or port for this `modes` entry in your configuration file.\"));\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tconsole.log();\n\n\t\t});\n\t}\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tblacklight.listen = async function(){\n\t\tawait initializeTo(\"listen\");\n\n\n\t\tvar servers=[];\n\t\tvar log=global.bl.logger.get(\"blacklight-core.vhost-lookup\");\n\t\tvar server;\n\t\tvar trustSlingSourceHeader = config.environment.trustSlingSourceHeader;\n\n\t\tfunction resolveVhost(req, res, thereIsNoNextWithoutExpress){\n\t\t\tvar port = req.socket.localPort;\n\t\t\tvar host = req.headers.host;\n\t\t\tvar server, usedSlingSource=false;\n\n\n\t\t\tif(trustSlingSourceHeader && req.headers[\"x-sling-source\"]){\n\t\t\t\tvar parts = req.headers[\"x-sling-source\"].split(\".\"), site, mode;\n\t\t\t\tif(parts[1]){\n\t\t\t\t\tsite=parts[0];\n\t\t\t\t\tmode=parts[1];\n\t\t\t\t}else{\n\t\t\t\t\tsite=blacklight.defaultSite;\n\t\t\t\t\tmode=parts[0];\n\t\t\t\t}\n\t\t\t\tvar id=site + \".\" + mode;\n\t\t\t\tserver = siteLookup[id];\n\t\t\t\tusedSlingSource = true;\n\n\t\t\t}else{\n\t\t\t\tif(!port && req.socket.address){\n\t\t\t\t\tport = req.socket.address().port || globalDefaultPort;\n\t\t\t\t}\n\n\t\t\t\tif (trustForwardedHostHeader && req.headers[\"x-forwarded-host\"]) {\n\t\t\t\t\thost = req.headers[\"x-forwarded-host\"];\n\t\t\t\t}\n\n\n\t\t\t\tif (host){\n\t\t\t\t\thost = host.split(':')[0];\n\t\t\t\t}else{\n\t\t\t\t\thost=\"*\";\n\t\t\t\t}\n\n\t\t\t\thost = host + \":\" + port;\n\n\t\t\t\tserver = hostLookup[host];\n\t\t\t\tif (!server){\n\t\t\t\t\thost = \"*\" + host.substr(host.indexOf(\".\"));\n\t\t\t\t\tserver = hostLookup[host];\n\t\t\t\t\thostLookup[host]=server;   // Auto-include this vhost entry into the lookup table.  TODO: infinitely variable wildcards + maliciousness could overfill this table.\n\t\t\t\t}\n\t\t\t\tif (!server){\n\t\t\t\t\t// TODO: make sure we don't allow an existing explicit hostname for a given mode to be resolved on the wrong port.\n\t\t\t\t\thost = \"*:\" + port;\n\t\t\t\t\tserver = hostLookup[host];\n\t\t\t\t\thostLookup[host]=server;   // Auto-include this vhost entry into the lookup table.  TODO: infinitely variable wildcards + maliciousness could overfill this table.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!server){\n\t\t\t\tlog.error(\"Failed to find host via \", (usedSlingSource ? (\"x-sling-source: \" + req.headers[\"x-sling-source\"]) : (\"hostname: \" + host)) );\n\t\t\t\tres.writeHead(404, {\"content-type\":\"text/html\"})\n\t\t\t\tres.write(\"Unknown host requested\\n\");\n\t\t\t\tres.end();\n\t\t\t}else{\n\t\t\t\treq.bl={...server.reqBl};\n\t\t\t\treq.bl.sling = req.bl.sling.cacheableClone(); \n\t\t\t\treturn server.app(req, res);\n\t\t\t}\n\n\t\t}\n\n\n\t\t_.each(portLookup, (portApp, port)=>{\n\t\t\tlog.info(\"Listening on port [\" + port + \"]\");\n\t\t\tservers.push(http.createServer(resolveVhost).listen(port));\n\t\t});\n\n\t\treturn servers;\n\n\t}\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tvar initializeTo=async function(endStep){\n\t\tvar stepIndex=initSteps.indexOf(endStep);\n\t\tif(stepIndex<0){throw new Error(\"Bad init step: \" + endStep);}\n\t\tvar prevStep=initSteps[stepIndex-1];\n\n\t\tif(prevStep && !initStatus[prevStep]){\n\t\t\tawait blacklight[prevStep]();\n\t\t}\n\n\t\tinitStatus[endStep]=true;\n\t}\n\n\n\n\t/**********************************************************************************/\n\t/**********************************************************************************/\n\tblacklight.pluginConfigHelper = function(site){\n\t\tvar computedSite = site || blacklight.defaultSite;\n\t\tvar slings;\n\t\tvar $={\n\t\t\tsite:site,\n\t\t\tconfig:config,\n\t\t\tsiteConfig:config[computedSite],\n\t\t\tsiteObject:blacklight.sites[computedSite],\n\t\t\tgetSlings: function(){\n\t\t\t\tif(!slings){\n\t\t\t\t\tslings={};\n\t\t\t\t\t/// TODO: don't regenerate sling object.  instead pull from siteLookup[site + \".\" + host];\n\t\t\t\t\t_.each(_.get(config,[computedSite,\"modes\"]), (host, mode)=>{\n\t\t\t\t\t\tif(host && host.sling){  slings[mode]= new SlingConnector(host.sling); }\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn slings;\n\t\t\t},\n\t\t\tgetEnv: (property, defaults)=>{\n\t\t\t\tvar propertyPath = \"environment.\" + property;\n\t\t\t\tvar val=_.get(config[site], propertyPath, _.get(config, propertyPath));\n\t\t\t\tif(typeof val === \"object\"){\n\t\t\t\t\tdefaults = typeof defaults === \"object\" ? defaults : {};\n\t\t\t\t\treturn _.assign(defaults, val);\n\t\t\t\t}else{\n\t\t\t\t\treturn val || defaults;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\treturn $;\n\t}\n\n\n\t/**********************************************************************************/\n\tfunction normalizePath(path){\n\t\treturn (path && path.replace) ? (path.replace(/\\/$/,\"\") + \"/\") : \"\";\n\t}\n\n\t/**********************************************************************************/\n\treturn blacklight;\n}\n\n\n\n"]}