1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.respond = exports.convertRequest = exports.convertHeaders = exports.createRequestHandler = void 0;
4const node_1 = require("@remix-run/node");
5const __1 = require("..");
6const environment_1 = require("../environment");
7/**
8 * Returns a request handler for Express that serves the response using Remix.
9 */
10function createRequestHandler({ build }, setup) {
11    const handleRequest = (0, __1.createRequestHandler)(build, setup);
12    return async (req, res, next) => {
13        if (!req?.url || !req.method) {
14            return next();
15        }
16        try {
17            const request = convertRequest(req, res);
18            const response = await handleRequest(request);
19            await respond(res, response);
20        }
21        catch (error) {
22            // Express doesn't support async functions, so we have to pass along the
23            // error manually using next().
24            next(error);
25        }
26    };
27}
28exports.createRequestHandler = createRequestHandler;
29function convertHeaders(requestHeaders) {
30    const headers = new node_1.Headers();
31    for (const [key, values] of Object.entries(requestHeaders)) {
32        if (values) {
33            if (Array.isArray(values)) {
34                for (const value of values) {
35                    headers.append(key, value);
36                }
37            }
38            else {
39                headers.set(key, values);
40            }
41        }
42    }
43    return headers;
44}
45exports.convertHeaders = convertHeaders;
46function convertRequest(req, res) {
47    const url = new URL(`${req.protocol}://${req.get('host')}${req.url}`);
48    // Abort action/loaders once we can no longer write a response
49    const controller = new node_1.AbortController();
50    res.on('close', () => controller.abort());
51    const init = {
52        method: req.method,
53        headers: convertHeaders(req.headers),
54        // Cast until reason/throwIfAborted added
55        // https://github.com/mysticatea/abort-controller/issues/36
56        signal: controller.signal,
57    };
58    if (req.method !== 'GET' && req.method !== 'HEAD') {
59        init.body = req;
60    }
61    return new environment_1.ExpoRequest(url.href, init);
62}
63exports.convertRequest = convertRequest;
64async function respond(res, expoRes) {
65    res.statusMessage = expoRes.statusText;
66    res.status(expoRes.status);
67    for (const [key, values] of Object.entries(expoRes.headers.raw())) {
68        for (const value of values) {
69            res.append(key, value);
70        }
71    }
72    if (expoRes.body) {
73        await (0, node_1.writeReadableStreamToWritable)(expoRes.body, res);
74    }
75    else {
76        res.end();
77    }
78}
79exports.respond = respond;
80//# sourceMappingURL=express.js.map