UNPKG

es-dev-server

Version:

Development server for modern web apps

153 lines 5.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRequestFilePath = exports.isGeneratedFile = exports.isInlineScript = exports.shouldTransformToModule = exports.isPolyfill = exports.SSEStream = exports.toFilePath = exports.toBrowserPath = exports.getBodyAsString = exports.isUtf8 = exports.IsBinaryFileError = exports.RequestCancelledError = exports.logDebug = exports.setDebug = void 0; const tslib_1 = require("tslib"); /* eslint-disable no-console, max-classes-per-file */ const is_stream_1 = tslib_1.__importDefault(require("is-stream")); const get_stream_1 = tslib_1.__importDefault(require("get-stream")); const stream_1 = tslib_1.__importDefault(require("stream")); const path_1 = tslib_1.__importDefault(require("path")); const mime_types_1 = tslib_1.__importDefault(require("mime-types")); const isbinaryfile_1 = require("isbinaryfile"); const constants_1 = require("../constants"); let _debug = false; function setDebug(debug) { _debug = debug; } exports.setDebug = setDebug; function logDebug(...messages) { if (_debug) { console.log('[es-dev-server]: ', ...messages.map(m => JSON.stringify(m))); } } exports.logDebug = logDebug; class RequestCancelledError extends Error { } exports.RequestCancelledError = RequestCancelledError; class IsBinaryFileError extends Error { } exports.IsBinaryFileError = IsBinaryFileError; /** * koa-static stores the original served file path on ctx.body.path, * we need this path for file transformation but we overwrite body * with a string, so we keep a reference with a weakmap */ const filePathsForRequests = new WeakMap(); function isUtf8(context) { const charSet = mime_types_1.default.charset(context.response.get('content-type')); return charSet === false ? false : charSet.toLowerCase() === 'utf-8'; } exports.isUtf8 = isUtf8; /** * Returns the body value as string. If the response is a stream, the * stream is drained and the result is returned. Because koa-static stores * a path variable on the stream, we need to create a new stream with * the same variable to preserve correct behavior. * */ async function getBodyAsString(ctx) { let requestCanceled; ctx.req.on('close', () => { requestCanceled = true; }); if (Buffer.isBuffer(ctx.body)) { return ctx.body.toString(); } if (typeof ctx.body === 'string') { return ctx.body; } if (is_stream_1.default(ctx.body)) { // cache request path, see above // @ts-ignore if (ctx.body.path) { // @ts-ignore filePathsForRequests.set(ctx.request, ctx.body.path); } // a stream can only be read once, so after reading it assign // the string response to the body so that it can be accessed // again later try { const bodyBuffer = await get_stream_1.default.buffer(ctx.body); const contentLength = Number(ctx.response.get('content-length')); if (await isbinaryfile_1.isBinaryFile(bodyBuffer, contentLength)) { ctx.body = bodyBuffer; throw new IsBinaryFileError(); } const bodyString = bodyBuffer.toString(); ctx.body = bodyString; return bodyString; } catch (error) { if (requestCanceled) { throw new RequestCancelledError(); } throw error; } } return ctx.body; } exports.getBodyAsString = getBodyAsString; /** * Turns a file path into a path suitable for browsers, with a / as seperator. * @param {string} filePath * @returns {string} */ function toBrowserPath(filePath) { return filePath.replace(new RegExp(path_1.default.sep === '\\' ? '\\\\' : path_1.default.sep, 'g'), '/'); } exports.toBrowserPath = toBrowserPath; /** * Transforms a file system path to a browser URL. For example windows uses `\` on the file system, * but it should use `/` in the browser. */ function toFilePath(browserPath) { return browserPath.replace(new RegExp('/', 'g'), path_1.default.sep); } exports.toFilePath = toFilePath; class SSEStream extends stream_1.default.Transform { sendMessage(name, data = '') { this.write(`event: ${name}\ndata: ${data}\n\n`); } _transform(data, enc, cb) { this.push(data.toString()); cb(); } } exports.SSEStream = SSEStream; function isPolyfill(url) { return url.includes('/polyfills/'); } exports.isPolyfill = isPolyfill; function shouldTransformToModule(url) { return url.includes('transform-systemjs'); } exports.shouldTransformToModule = shouldTransformToModule; function isInlineScript(url) { return url.includes(`inline-script-`) && url.includes('?source='); } exports.isInlineScript = isInlineScript; /** * Returns whether this is a file generated generated by the dev server */ function isGeneratedFile(url) { return url.startsWith(constants_1.virtualFilePrefix) || isPolyfill(url) || isInlineScript(url); } exports.isGeneratedFile = isGeneratedFile; function getRequestFilePath(ctx, rootDir) { if (isPolyfill(ctx.url)) { return null; } // inline module requests have the source in a query string if (isInlineScript(ctx.url)) { const url = ctx.url.split('?')[0]; const indexPath = toFilePath(url); return path_1.default.join(rootDir, indexPath); } // otherwise koa-static adds the original file path on the body if (ctx.body && ctx.body.path) { return ctx.body.path; } return filePathsForRequests.get(ctx.request) || null; } exports.getRequestFilePath = getRequestFilePath; //# sourceMappingURL=utils.js.map