import { fromDurableResponse, fromRequest, getFetchHeadersObject } from "../../data/index.js";
import { createServiceWorkerWorker, executeServiceWorkerWorker } from "./execute.js";
import { isLike } from "../../is.js";
import { getOrigin } from "../../listen/config.js";
export function createServiceWorkerFetch(registration, serviceWorkerInit, pushable) {
    let workerPromise = undefined;
    return async (input, init) => {
        workerPromise = workerPromise || (pushable ? undefined : createServiceWorkerWorker());
        let request;
        if (input instanceof Request) {
            request = input;
        }
        else if (init?.body) {
            request = new Request(typeof input === "string" ?
                new URL(input, getOrigin()).toString() :
                input, {
                duplex: "half",
                ...init,
            });
        }
        else {
            request = {
                url: new URL(input, getOrigin()).toString(),
                method: init?.method,
                headers: getFetchHeadersObject(new Headers(init?.headers))
            };
        }
        return executeServiceWorkerFetch(registration, request, init, serviceWorkerInit, pushable ?? await workerPromise);
    };
}
export async function executeServiceWorkerFetch(registration, request, options, serviceWorkerInit, pushable) {
    return executeServiceWorkerFetchEvent(registration, {
        type: "fetch",
        request: request instanceof Request ?
            await fromRequest(request) :
            request,
        virtual: true,
        dispatch: options?.dispatch,
        entrypoint: options?.entrypoint,
        entrypointArguments: options?.entrypointArguments
    }, serviceWorkerInit);
}
export async function executeServiceWorkerFetchEvent(registration, event, serviceWorkerInit, pushable) {
    const { MessageChannel } = await import("node:worker_threads");
    let data;
    const input = {
        ...serviceWorkerInit,
        serviceWorkerId: registration.durable.serviceWorkerId,
        event,
        channel: new MessageChannel()
    };
    if (pushable) {
        data = pushable.push(input);
    }
    else {
        data = executeServiceWorkerWorker(input);
    }
    const iterator = data[Symbol.asyncIterator]();
    return getResponse();
    async function getResponse() {
        const message = await next();
        if (!message) {
            throw new Error("Unable to retrieve response");
        }
        return fromDurableResponse(message.response);
    }
    async function next() {
        const { value, done } = await iterator.next();
        if (done) {
            await iterator.return?.();
        }
        if (!isLike(value)) {
            return undefined;
        }
        return value;
    }
}
//# sourceMappingURL=execute-fetch.js.map