@ -5,75 +5,23 @@ const defaultValue = require("default-value");
const assureArray = require ( "assure-array" ) ;
const path = require ( "path" ) ;
const entities = require ( "entities" ) ;
const util = require ( "util" ) ;
let reloadClientTag = Buffer . from ( "<script src=\"/budo/livereload.js\"></script>" ) ;
function monkeyPatchEnd ( res ) {
// NOTE: This is a hack, to auto-inject the Budo livereload client in any outgoing HTML response (but only in development mode).
let end = res . end . bind ( res ) ;
res . end = function monkeyPatchedEnd ( ... args ) {
let originalChunk = args [ 0 ] ;
let prefix ;
if ( originalChunk == null || typeof originalChunk === "string" || Buffer . isBuffer ( originalChunk ) ) {
if ( ! res . headersSent ) {
// If headers have already been sent, we'll just have to hope that the browser will still look at our appended tag, as we can't change the response size anymore...
// TODO: Make this more robust in the future
let typeHeader = res . getHeader ( "content-type" ) ;
if ( typeHeader != null && typeHeader . startsWith ( "text/html" ) ) {
let contentLength = res . getHeader ( "content-length" ) ;
if ( contentLength != null ) {
// Compensate for the additional bytes introduced by our injected script tag
res . setHeader ( "content-length" , parseInt ( contentLength ) + reloadClientTag . length ) ;
}
prefix = reloadClientTag ;
}
}
// Reset the `end` method back to the original method; we don't need to get in the way anymore
res . end = end ;
let originalChunkAsBuffer = ( typeof originalChunk === "string" )
? Buffer . from ( originalChunk )
: originalChunk ;
if ( prefix != null ) {
let chunk = ( originalChunkAsBuffer == null )
? reloadClientTag
: Buffer . concat ( [ originalChunkAsBuffer , reloadClientTag ] ) ;
end ( chunk , ... args . slice ( 1 ) ) ;
} else {
end ( ... args ) ;
}
} else {
throw new Error ( ` Expected a buffer or string in 'end', but got something else: ${ util . inspect ( args [ 0 ] ) } ` ) ;
}
} ;
}
const stacked = require ( "stacked" ) ;
const injectLRScript = require ( "inject-lr-script" ) ;
function createExpressMiddleware ( app , fullBundlePath ) {
return function expressMiddleware ( req , res , next ) {
try {
monkeyPatchEnd ( res ) ;
} catch ( error ) {
process . nextTick ( ( ) => {
throw error ;
} ) ;
}
let handler = stacked ( ) ;
handler . use ( injectLRScript ( { local : true , path : "/budo/livereload.js" } ) ) ;
handler . use ( ( req , res , next ) => {
// Ensure that we never intercept budo-served resources. Otherwise, the Express app might have something like a 404 handler or "always require login" middleware that stops requests for budo assets from ever coming out the other end of the Express app.
if ( req . url !== "/budo/livereload.js" && req . url !== ` / ${ fullBundlePath } ` ) {
app . handle ( req , res , ( err ) => {
if ( err != null && err instanceof Error ) {
res
. status ( 500 )
. send ( ` ${ reloadClientTag } <pre> ${ entities . escape ( err . stack ) } </pre> ` ) ;
. set ( "content-type" , "text/html" )
. send ( ` <pre> ${ entities . escape ( err . stack ) } </pre> ` ) ;
} else {
next ( err ) ;
}
@ -81,7 +29,7 @@ function createExpressMiddleware(app, fullBundlePath) {
} else {
next ( ) ;
}
} ;
} ) ;
}
module . exports = function ( { options , staticPath , staticBasePath , entryPaths , host } ) {