"use strict";
/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ClientSDK_httpClient, _ClientSDK_hooks, _ClientSDK_logger;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientSDK = void 0;
const hooks_js_1 = require("../hooks/hooks.js");
const httpclienterrors_js_1 = require("../models/errors/httpclienterrors.js");
const fp_js_1 = require("../types/fp.js");
const base64_js_1 = require("./base64.js");
const config_js_1 = require("./config.js");
const encodings_js_1 = require("./encodings.js");
const env_js_1 = require("./env.js");
const http_js_1 = require("./http.js");
const retries_js_1 = require("./retries.js");
const gt = typeof globalThis === "undefined" ? null : globalThis;
const webWorkerLike = typeof gt === "object"
    && gt != null
    && "importScripts" in gt
    && typeof gt["importScripts"] === "function";
const isBrowserLike = webWorkerLike
    || (typeof navigator !== "undefined" && "serviceWorker" in navigator)
    || (typeof window === "object" && typeof window.document !== "undefined");
class ClientSDK {
    constructor(options = {}) {
        _ClientSDK_httpClient.set(this, void 0);
        _ClientSDK_hooks.set(this, void 0);
        _ClientSDK_logger.set(this, void 0);
        const opt = options;
        if (typeof opt === "object"
            && opt != null
            && "hooks" in opt
            && opt.hooks instanceof hooks_js_1.SDKHooks) {
            __classPrivateFieldSet(this, _ClientSDK_hooks, opt.hooks, "f");
        }
        else {
            __classPrivateFieldSet(this, _ClientSDK_hooks, new hooks_js_1.SDKHooks(), "f");
        }
        this._options = { ...options, hooks: __classPrivateFieldGet(this, _ClientSDK_hooks, "f") };
        const url = (0, config_js_1.serverURLFromOptions)(options);
        if (url) {
            url.pathname = url.pathname.replace(/\/+$/, "") + "/";
        }
        const { baseURL, client } = __classPrivateFieldGet(this, _ClientSDK_hooks, "f").sdkInit({
            baseURL: url,
            client: options.httpClient || new http_js_1.HTTPClient(),
        });
        this._baseURL = baseURL;
        __classPrivateFieldSet(this, _ClientSDK_httpClient, client, "f");
        __classPrivateFieldSet(this, _ClientSDK_logger, options.debugLogger, "f");
        if (!__classPrivateFieldGet(this, _ClientSDK_logger, "f") && (0, env_js_1.env)().ONEROSTER_DEBUG) {
            __classPrivateFieldSet(this, _ClientSDK_logger, console, "f");
        }
    }
    _createRequest(context, conf, options) {
        const { method, path, query, headers: opHeaders, security } = conf;
        const base = conf.baseURL ?? this._baseURL;
        if (!base) {
            return (0, fp_js_1.ERR)(new httpclienterrors_js_1.InvalidRequestError("No base URL provided for operation"));
        }
        const reqURL = new URL(base);
        const inputURL = new URL(path, reqURL);
        if (path) {
            reqURL.pathname += reqURL.pathname.endsWith("/") ? "" : "/";
            reqURL.pathname += inputURL.pathname.replace(/^\/+/, "");
        }
        let finalQuery = query || "";
        const secQuery = [];
        for (const [k, v] of Object.entries(security?.queryParams || {})) {
            const q = (0, encodings_js_1.encodeForm)(k, v, { charEncoding: "percent" });
            if (typeof q !== "undefined") {
                secQuery.push(q);
            }
        }
        if (secQuery.length) {
            finalQuery += `&${secQuery.join("&")}`;
        }
        if (finalQuery) {
            const q = finalQuery.startsWith("&") ? finalQuery.slice(1) : finalQuery;
            reqURL.search = `?${q}`;
        }
        const headers = new Headers(opHeaders);
        const username = security?.basic.username;
        const password = security?.basic.password;
        if (username != null || password != null) {
            const encoded = (0, base64_js_1.stringToBase64)([username || "", password || ""].join(":"));
            headers.set("Authorization", `Basic ${encoded}`);
        }
        const securityHeaders = new Headers(security?.headers || {});
        for (const [k, v] of securityHeaders) {
            headers.set(k, v);
        }
        let cookie = headers.get("cookie") || "";
        for (const [k, v] of Object.entries(security?.cookies || {})) {
            cookie += `; ${k}=${v}`;
        }
        cookie = cookie.startsWith("; ") ? cookie.slice(2) : cookie;
        headers.set("cookie", cookie);
        const userHeaders = new Headers(options?.headers ?? options?.fetchOptions?.headers);
        for (const [k, v] of userHeaders) {
            headers.set(k, v);
        }
        // Only set user agent header in non-browser-like environments since CORS
        // policy disallows setting it in browsers e.g. Chrome throws an error.
        if (!isBrowserLike) {
            headers.set(conf.uaHeader ?? "user-agent", config_js_1.SDK_METADATA.userAgent);
        }
        const fetchOptions = {
            ...options?.fetchOptions,
            ...options,
        };
        if (!fetchOptions?.signal && conf.timeoutMs && conf.timeoutMs > 0) {
            const timeoutSignal = AbortSignal.timeout(conf.timeoutMs);
            fetchOptions.signal = timeoutSignal;
        }
        if (conf.body instanceof ReadableStream) {
            Object.assign(fetchOptions, { duplex: "half" });
        }
        let input;
        try {
            input = __classPrivateFieldGet(this, _ClientSDK_hooks, "f").beforeCreateRequest(context, {
                url: reqURL,
                options: {
                    ...fetchOptions,
                    body: conf.body ?? null,
                    headers,
                    method,
                },
            });
        }
        catch (err) {
            return (0, fp_js_1.ERR)(new httpclienterrors_js_1.UnexpectedClientError("Create request hook failed to execute", {
                cause: err,
            }));
        }
        return (0, fp_js_1.OK)(new Request(input.url, input.options));
    }
    async _do(request, options) {
        const { context, errorCodes } = options;
        return (0, retries_js_1.retry)(async () => {
            const req = await __classPrivateFieldGet(this, _ClientSDK_hooks, "f").beforeRequest(context, request.clone());
            await logRequest(__classPrivateFieldGet(this, _ClientSDK_logger, "f"), req).catch((e) => __classPrivateFieldGet(this, _ClientSDK_logger, "f")?.log("Failed to log request:", e));
            let response = await __classPrivateFieldGet(this, _ClientSDK_httpClient, "f").request(req);
            try {
                if ((0, http_js_1.matchStatusCode)(response, errorCodes)) {
                    const result = await __classPrivateFieldGet(this, _ClientSDK_hooks, "f").afterError(context, response, null);
                    if (result.error) {
                        throw result.error;
                    }
                    response = result.response || response;
                }
                else {
                    response = await __classPrivateFieldGet(this, _ClientSDK_hooks, "f").afterSuccess(context, response);
                }
            }
            finally {
                await logResponse(__classPrivateFieldGet(this, _ClientSDK_logger, "f"), response, req)
                    .catch(e => __classPrivateFieldGet(this, _ClientSDK_logger, "f")?.log("Failed to log response:", e));
            }
            return response;
        }, { config: options.retryConfig, statusCodes: options.retryCodes }).then((r) => (0, fp_js_1.OK)(r), (err) => {
            switch (true) {
                case (0, http_js_1.isAbortError)(err):
                    return (0, fp_js_1.ERR)(new httpclienterrors_js_1.RequestAbortedError("Request aborted by client", {
                        cause: err,
                    }));
                case (0, http_js_1.isTimeoutError)(err):
                    return (0, fp_js_1.ERR)(new httpclienterrors_js_1.RequestTimeoutError("Request timed out", { cause: err }));
                case (0, http_js_1.isConnectionError)(err):
                    return (0, fp_js_1.ERR)(new httpclienterrors_js_1.ConnectionError("Unable to make request", { cause: err }));
                default:
                    return (0, fp_js_1.ERR)(new httpclienterrors_js_1.UnexpectedClientError("Unexpected HTTP client error", {
                        cause: err,
                    }));
            }
        });
    }
}
exports.ClientSDK = ClientSDK;
_ClientSDK_httpClient = new WeakMap(), _ClientSDK_hooks = new WeakMap(), _ClientSDK_logger = new WeakMap();
const jsonLikeContentTypeRE = /(application|text)\/.*?\+*json.*/;
const jsonlLikeContentTypeRE = /(application|text)\/(.*?\+*\bjsonl\b.*|.*?\+*\bx-ndjson\b.*)/;
async function logRequest(logger, req) {
    if (!logger) {
        return;
    }
    const contentType = req.headers.get("content-type");
    const ct = contentType?.split(";")[0] || "";
    logger.group(`> Request: ${req.method} ${req.url}`);
    logger.group("Headers:");
    for (const [k, v] of req.headers.entries()) {
        logger.log(`${k}: ${v}`);
    }
    logger.groupEnd();
    logger.group("Body:");
    switch (true) {
        case jsonLikeContentTypeRE.test(ct):
            logger.log(await req.clone().json());
            break;
        case ct.startsWith("text/"):
            logger.log(await req.clone().text());
            break;
        case ct === "multipart/form-data": {
            const body = await req.clone().formData();
            for (const [k, v] of body) {
                const vlabel = v instanceof Blob ? "<Blob>" : v;
                logger.log(`${k}: ${vlabel}`);
            }
            break;
        }
        default:
            logger.log(`<${contentType}>`);
            break;
    }
    logger.groupEnd();
    logger.groupEnd();
}
async function logResponse(logger, res, req) {
    if (!logger) {
        return;
    }
    const contentType = res.headers.get("content-type");
    const ct = contentType?.split(";")[0] || "";
    logger.group(`< Response: ${req.method} ${req.url}`);
    logger.log("Status Code:", res.status, res.statusText);
    logger.group("Headers:");
    for (const [k, v] of res.headers.entries()) {
        logger.log(`${k}: ${v}`);
    }
    logger.groupEnd();
    logger.group("Body:");
    switch (true) {
        case (0, http_js_1.matchContentType)(res, "application/json")
            || jsonLikeContentTypeRE.test(ct) && !jsonlLikeContentTypeRE.test(ct):
            logger.log(await res.clone().json());
            break;
        case (0, http_js_1.matchContentType)(res, "application/jsonl")
            || jsonlLikeContentTypeRE.test(ct):
            logger.log(await res.clone().text());
            break;
        case (0, http_js_1.matchContentType)(res, "text/event-stream"):
            logger.log(`<${contentType}>`);
            break;
        case (0, http_js_1.matchContentType)(res, "text/*"):
            logger.log(await res.clone().text());
            break;
        case (0, http_js_1.matchContentType)(res, "multipart/form-data"): {
            const body = await res.clone().formData();
            for (const [k, v] of body) {
                const vlabel = v instanceof Blob ? "<Blob>" : v;
                logger.log(`${k}: ${vlabel}`);
            }
            break;
        }
        default:
            logger.log(`<${contentType}>`);
            break;
    }
    logger.groupEnd();
    logger.groupEnd();
}
//# sourceMappingURL=sdks.js.map