import { HttpRequest, Headers, ApiError } from "@api-client/core/build/browser.js";
import { Events } from "../../events/Events.js";
import { ProxyBindings } from "../base/ProxyBindings.js";
/**
 * A class that acts as an HTTP proxy for the application.
 * Since the Project runner and the CoreEngine are strictly NodeJS modules, this needs to proxy the request to the server that supports
 * this API to make the request.
 *
 * When using the proxy, the logic first sends request to the proxy with initialization values: the request data, authorization, and configuration.
 * In response, the proxy server responds with a URL (or a path) to use to send the body. The method of the request is used with the second request.
 * The proxy detects payload for requests other than GET and HEAD.
 */
export class WebProxyBindings extends ProxyBindings {
    /**
     * @param app The application information
     * @param proxyUrl The base URI to the HTTP proxy.
     * @param authenticate Whether to use the current store environment to send authentication credentials.
     */
    constructor(app, proxyUrl, init = {}) {
        super(app);
        this.proxyUrl = proxyUrl;
        /**
         * Whether to use the current store environment to send the authentication credentials
         * with the proxy request. This is required when using the `net-store`.
         */
        this.authenticate = false;
        if (typeof init.authenticate === 'boolean') {
            this.authenticate = init.authenticate;
        }
    }
    async listHeaders() {
        const result = {
            'content-type': 'application/json',
        };
        if (this.authenticate) {
            const env = await Events.Store.Global.getEnv();
            if (!env || !env.token) {
                throw new Error(`You are not authorized in the store to make a proxy request.`);
            }
            result.authorization = `Bearer ${env.token}, ${env.location}`;
        }
        return result;
    }
    async proxy(body) {
        const copy = { ...body };
        const { signal } = copy;
        delete copy.signal;
        const headers = await this.listHeaders();
        const init = {
            body: JSON.stringify(body),
            method: 'POST',
            headers,
            cache: 'no-cache',
            signal,
        };
        const response = await fetch(this.proxyUrl, init);
        if (response.status !== 200) {
            const error = await response.json();
            throw new ApiError(error);
        }
        return response.json();
    }
    async coreRequest(init) {
        return this.proxy(init);
    }
    async coreHttpProject(init) {
        return this.proxy(init);
    }
    async httpSend(request, init = {}) {
        const config = { ...init };
        if (request.headers) {
            if (!config.headers) {
                config.headers = {};
            }
            const parser = new Headers(request.headers);
            const headers = config.headers;
            parser.forEach((value, name) => {
                if (headers[name]) {
                    headers[name] += `, ${value}`;
                }
                else {
                    headers[name] = value;
                }
            });
        }
        if (request.method) {
            config.method = request.method;
        }
        if (request.payload) {
            const r = new HttpRequest(request);
            const payload = await r.readPayload();
            config.body = payload;
        }
        return fetch(request.url, config);
    }
}
//# sourceMappingURL=WebProxyBindings.js.map