UNPKG

@universal-middleware/compress

Version:
202 lines (198 loc) 6.08 kB
import { createRequestAdapter, sendResponse, responseAdapter, setResponseHeaders } from './chunk-DZTR7BGC.js'; import { bindUniversal, contextSymbol, universalSymbol, getAdapterRuntime } from './chunk-A5W3PKM7.js'; import { middleware_default } from './chunk-OE4YTAMF.js'; import 'node:http'; import 'node:stream'; var pendingMiddlewaresSymbol = /* @__PURE__ */ Symbol.for("unPendingMiddlewares"); var wrappedResponseSymbol = /* @__PURE__ */ Symbol.for("unWrappedResponse"); function createTransformStream() { const textEncoder = new TextEncoder(); return new TransformStream({ transform(chunk, ctrl) { if (typeof chunk === "string") { ctrl.enqueue(textEncoder.encode(chunk)); } else if (chunk instanceof Uint8Array) { ctrl.enqueue(chunk); } else { ctrl.enqueue(new Uint8Array(chunk)); } } }); } function override(nodeResponse, key, forwardTo) { const original = nodeResponse[key]; nodeResponse[key] = (...args) => { if (!nodeResponse.headersSent) { nodeResponse.writeHead(nodeResponse.statusCode); } if (args[0] && args[0].length > 0) { forwardTo.write(args[0]).catch(console.error); } if (key === "end") { forwardTo.close().catch(() => { }); } return true; }; return { original(...args) { original.apply(nodeResponse, args); }, restore() { nodeResponse[key] = original; } }; } function overrideWriteHead(nodeResponse, callback) { const original = nodeResponse.writeHead; let alreadyCalled = false; nodeResponse.writeHead = () => { if (!alreadyCalled) { callback().catch(console.error); alreadyCalled = true; } return nodeResponse; }; return { original(...args) { original.apply(nodeResponse, args); }, restore() { nodeResponse.writeHead = original; } }; } function wrapResponse(nodeResponse, next) { if (nodeResponse[wrappedResponseSymbol]) return; nodeResponse[wrappedResponseSymbol] = true; const body = createTransformStream(); const writer = body.writable.getWriter(); const [reader1, reader2] = body.readable.tee(); const original = { write: override(nodeResponse, "write", writer), end: override(nodeResponse, "end", writer), writeHead: overrideWriteHead(nodeResponse, triggerPendingMiddlewares) }; async function triggerPendingMiddlewares() { if (!nodeResponse[pendingMiddlewaresSymbol]) { return; } const middlewares = nodeResponse[pendingMiddlewaresSymbol]; delete nodeResponse[pendingMiddlewaresSymbol]; let response; try { response = responseAdapter(nodeResponse, reader1); for (const middleware of middlewares) { const tmp = await middleware(response); if (tmp) response = tmp; } } catch (e) { response = void 0; await writer.abort(); original.writeHead.restore(); original.write.restore(); original.end.restore(); if (next) { next(e); } else { throw e; } } if (!response) return; const readableToOriginal = response.body ?? reader2; setResponseHeaders(response, nodeResponse, true); original.writeHead.restore(); nodeResponse.flushHeaders(); const wait = readableToOriginal.pipeTo( new WritableStream({ write(chunk) { original.write.original(chunk); }, close() { original.end.original(); }, abort() { original.end.original(); } }) ); await wait; original.write.restore(); original.end.restore(); } } function nextOr404(res, next) { if (next) { next(); } else { res.statusCode = 404; res.end(); } } function createMiddleware(middlewareFactory, options = {}) { const requestAdapter = createRequestAdapter(options); return (...args) => { const middleware = middlewareFactory(...args); return bindUniversal(middleware, async function universalMiddlewareExpress(req, res, next) { try { req[contextSymbol] ??= {}; const request = requestAdapter(req, res); const response = await this[universalSymbol](request, getContext(req), getRuntime(req, res)); if (!response) { return nextOr404(res, next); } if (typeof response === "function") { if (res.headersSent) { throw new Error( "Universal Middleware called after headers have been sent. Please open an issue at https://github.com/magne4000/universal-middleware" ); } if (req.complete === void 0) req.complete = req._readableState?.ended ?? true; wrapResponse(res, next); res[pendingMiddlewaresSymbol] ??= []; res[pendingMiddlewaresSymbol].push(response); return nextOr404(res, next); } if (response instanceof Response) { await sendResponse(response, res); } else { req[contextSymbol] = response; return nextOr404(res, next); } } catch (error) { if (next) { next(error); } else { console.error(error); if (!res.headersSent) { res.statusCode = 500; } if (!res.writableEnded) { res.end(); } } } }); }; } function getContext(req) { return req[contextSymbol]; } function getRuntime(request, response) { return getAdapterRuntime("express", { params: request.params, // biome-ignore lint/suspicious/noExplicitAny: cast req: request, // biome-ignore lint/suspicious/noExplicitAny: cast res: response, express: Object.freeze({ // biome-ignore lint/suspicious/noExplicitAny: cast req: request, // biome-ignore lint/suspicious/noExplicitAny: cast res: response }) }); } // virtual:universal-middleware:virtual:universal-middleware:express:middleware:src/middleware.ts var middleware_default2 = createMiddleware(middleware_default); export { middleware_default2 as default };