import { createContext } from "effection";
import { assertIsHTMLNode } from "./assertions.js";
import { serializeHtml } from "./middleware/serialize-html.js";
import { concat, dispatch, httpResponsesMiddleware, respondNotFound, } from "./middleware.js";
import { useServer } from "./server.js";
export function createRevolution(options = {}) {
    let handler = createApp(options);
    return {
        *start({ port } = {}) {
            let server = yield* useServer({ handler, port });
            return server;
        },
    };
}
const RevolutionOptions = createContext("revolution.options");
export function* useRevolutionOptions() {
    return yield* RevolutionOptions;
}
function createApp({ app: middlewares = [], plugins = [], }) {
    let html = concat(...plugins.flatMap((plugin) => [plugin.html ?? []].flat()));
    let http = concat(...plugins.flatMap((plugin) => [plugin.http ?? []].flat()));
    let app = concat(...middlewares.map((middleware) => {
        return function* (request, next) {
            //@ts-expect-error the JSX Element is always mapped into Response
            const result = yield* middleware(request, next);
            if (result instanceof Response) {
                return result;
            }
            else {
                assertIsHTMLNode(result);
                let element = yield* html(request, function* () {
                    return result;
                });
                return serializeHtml(element);
            }
        };
    }));
    let options = function* revolutionOptions(request, next) {
        yield* RevolutionOptions.set({ app: middlewares, plugins });
        return yield* next(request);
    };
    let handler = concat(options, httpResponsesMiddleware(), http, app);
    return dispatch(handler, respondNotFound);
}
//# sourceMappingURL=revolution.js.map