UNPKG

systemjs-tools

Version:
174 lines (151 loc) 5.99 kB
const path = require('path') const express = require('express') const defaultFinalHandler = require('finalhandler') const merge = require('deepmerge') const httpProxy = require('http-proxy') const url = require('url') // var spdy = require('spdy-push'); export const analyse = (req, res) => { const accept = req.get('accept'); const initiatedBySystemJS = accept && accept.indexOf('application/x-es-module') !== -1 return {initiatedBySystemJS} } export const makeHandlers = ({_, config}) => { const handlers = { static: (options = {}) => express.static(path.join(config.directories.root, config.serve.dir), options), bundle: (options = {}) => (req, res, next) => { const {bundleTrigger} = merge({ bundleTrigger: 'dependencies.js' }, options) // Request can match with string, function or regex. const matchRequest = (req, match) => typeof match === 'string' && (req.originalUrl.endsWith(match) || req.originalUrl.endsWith(match + '.map')) || typeof match === 'function' && match(req) || typeof match === 'object' && (match instanceof RegExp) && match.exec(req.originalUrl); // Simple case: mapping bundle trigger to request. let builder; if (matchRequest(req, bundleTrigger)) { builder = {expression: config.entries.join(' + ')} // Didn't match; look for mappings overrides. } else { (config.mappings || []).forEach(mapping => { if (matchRequest(req, mapping.match)) { if (!mapping.builder) { throw new Error('Builder options missing for mapping: ' + mapping.match); } builder = mapping.builder; } }); } // Is this a mapped builder request? if (builder) { const builderOptions = merge(config.builder.options, builder.options || {}); if (req.originalUrl.endsWith('.map')) { _.log(`requesting ${req.url} retrieving external sourcemap`) _.bundle(builder.expression, builderOptions).then(({sourceMap}) => res.end(sourceMap)) } else { _.log(`requesting ${req.url} triggering bundling`) _.bundle(builder.expression, builderOptions).then(({source, sourceMap}) => res.end( options.sourceMaps === 'inline' || !sourceMap ? source : source + `\n//# sourceMappingURL=${path.basename(req.originalUrl)}.map`)) } } else { next() } }, // compile: () => (req, res, next) => { // const toCompile = req.originalUrl.substring(1) // // _.log(':: Compiling ', toCompile) // _.then('build', () => ( // _.builder.compile(toCompile, config.builder.options).then(m => { // res.end(m.source) // console.log(':: Finished Compiling ', toCompile) // }) // ) // ) // }, proxyHandler: (options = {}) => { const proxyUrl = config.proxy || options.proxy; _.log('setting up proxy to ' + proxyUrl) let proxy = httpProxy.createProxyServer({protocolRewrite: 'https:', autoRewrite: true, secure: ('secure' in options ? options.secure : false)}) let target = url.parse(proxyUrl) proxy.on('proxyReq', (proxyReq, req, res, proxyOptions) => { proxyReq.setHeader('X-Forwarded-Proto', 'https') }) proxy.on('proxyRes', (proxyRes, req, res, proxyOptions) => { var location = proxyRes.headers['location'] if (location) { var u = url.parse(location) u.host = target.host proxyRes.headers['location'] = url.format(u) } delete proxyRes.headers['transfer-encoding'] }) proxy.on('error', function(e) { console.error(e) }) return (req, res, next) => { _.log(`${req.method} https://${req.headers.host}${req.originalUrl} => ${proxyUrl}`) return proxy.web(req, res, { target: proxyUrl }); } }, fallthroughHandler: (options = {}) => { const {fallthroughHandler} = merge({ fallthroughHandler: (req, res) => { defaultFinalHandler(req, res)() } }, options); return fallthroughHandler; }, defaultHandler: (options = {}) => { const app = express() app.use(handlers.bundle()) app.use(handlers.static()) if (config.proxy) { app.use(handlers.proxyHandler()) } app.use(handlers.fallthroughHandler()) return app } } // const pushDeps = (req, res, next) => { // // const {} = analyse(req, res) // // tools._thenBuild( // tools.builder.trace(req.originalUrl.slice(1)).then(trace => { // return Promise.all(Object.keys(trace).map(depName => { // return tools.jspm.normalize(depName).then(normalized => { // return tools.builder.compile(normalized).then(compiled => { // console.log('successfully compiled <>', path.relative(tools.serverRoot, trace[depName].path)) // var stream = res.push('/' + path.relative(tools.serverRoot, trace[depName].path), { // status: 200, // optional // method: 'GET', // optional // request: { // accept: 'application/x-es-module, */*' // }, // response: { // 'content-type': 'application/javascript' // } // }); // stream.on('error', function (e) { // console.log(e) // }); // stream.end(compiled.source); // // return Promise.resolve(depName) // // }).catch((e) => { // console.error("Failed to compile ", depName, e) // return false // }) // }) // })) // }).then(compiled => { // tools.builder.compile('app/app.js').then((compiled) => res.end(compiled.source)) // }) // ) // } return handlers }