"use strict";
/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.jsonErr = jsonErr;
exports.json = json;
exports.textErr = textErr;
exports.text = text;
exports.bytesErr = bytesErr;
exports.bytes = bytes;
exports.streamErr = streamErr;
exports.stream = stream;
exports.sseErr = sseErr;
exports.sse = sse;
exports.nilErr = nilErr;
exports.nil = nil;
exports.fail = fail;
exports.match = match;
exports.unpackHeaders = unpackHeaders;
exports.discardResponseBody = discardResponseBody;
const sdkerror_js_1 = require("../models/errors/sdkerror.js");
const event_streams_js_1 = require("./event-streams.js");
const http_js_1 = require("./http.js");
const is_plain_object_js_1 = require("./is-plain-object.js");
const schemas_js_1 = require("./schemas.js");
const DEFAULT_CONTENT_TYPES = {
    json: "application/json",
    text: "text/plain",
    bytes: "application/octet-stream",
    stream: "application/octet-stream",
    sse: "text/event-stream",
    nil: "*",
    fail: "*",
};
function jsonErr(codes, schema, options) {
    return { ...options, err: true, enc: "json", codes, schema };
}
function json(codes, schema, options) {
    return { ...options, enc: "json", codes, schema };
}
function textErr(codes, schema, options) {
    return { ...options, err: true, enc: "text", codes, schema };
}
function text(codes, schema, options) {
    return { ...options, enc: "text", codes, schema };
}
function bytesErr(codes, schema, options) {
    return { ...options, err: true, enc: "bytes", codes, schema };
}
function bytes(codes, schema, options) {
    return { ...options, enc: "bytes", codes, schema };
}
function streamErr(codes, schema, options) {
    return { ...options, err: true, enc: "stream", codes, schema };
}
function stream(codes, schema, options) {
    return { ...options, enc: "stream", codes, schema };
}
function sseErr(codes, schema, options) {
    return { ...options, err: true, enc: "sse", codes, schema };
}
function sse(codes, schema, options) {
    return { ...options, enc: "sse", codes, schema };
}
function nilErr(codes, schema, options) {
    return { ...options, err: true, enc: "nil", codes, schema };
}
function nil(codes, schema, options) {
    return { ...options, enc: "nil", codes, schema };
}
function fail(codes) {
    return { enc: "fail", codes };
}
function match(...matchers) {
    return async function matchFunc(response, options) {
        let raw;
        let matcher;
        for (const match of matchers) {
            const { codes } = match;
            const ctpattern = "ctype" in match
                ? match.ctype
                : DEFAULT_CONTENT_TYPES[match.enc];
            if (ctpattern && (0, http_js_1.matchResponse)(response, codes, ctpattern)) {
                matcher = match;
                break;
            }
            else if (!ctpattern && (0, http_js_1.matchStatusCode)(response, codes)) {
                matcher = match;
                break;
            }
        }
        if (!matcher) {
            const responseBody = await response.text();
            return [{
                    ok: false,
                    error: new sdkerror_js_1.SDKError("Unexpected API response status or content-type", response, responseBody),
                }, responseBody];
        }
        const encoding = matcher.enc;
        switch (encoding) {
            case "json":
                raw = await response.json();
                break;
            case "bytes":
                raw = new Uint8Array(await response.arrayBuffer());
                break;
            case "stream":
                raw = response.body;
                break;
            case "text":
                raw = await response.text();
                break;
            case "sse":
                raw = response.body && matcher.sseSentinel
                    ? (0, event_streams_js_1.discardSentinel)(response.body, matcher.sseSentinel)
                    : response.body;
                break;
            case "nil":
                raw = await discardResponseBody(response);
                break;
            case "fail":
                raw = await response.text();
                break;
            default:
                encoding;
                throw new Error(`Unsupported response type: ${encoding}`);
        }
        if (matcher.enc === "fail") {
            return [{
                    ok: false,
                    error: new sdkerror_js_1.SDKError("API error occurred", response, typeof raw === "string" ? raw : ""),
                }, raw];
        }
        const resultKey = matcher.key || options?.resultKey;
        let data;
        if ("err" in matcher) {
            data = {
                ...options?.extraFields,
                ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null),
                ...((0, is_plain_object_js_1.isPlainObject)(raw) ? raw : null),
            };
        }
        else if (resultKey) {
            data = {
                ...options?.extraFields,
                ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null),
                [resultKey]: raw,
            };
        }
        else if (matcher.hdrs) {
            data = {
                ...options?.extraFields,
                ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null),
                ...((0, is_plain_object_js_1.isPlainObject)(raw) ? raw : null),
            };
        }
        else {
            data = raw;
        }
        if ("err" in matcher) {
            const result = (0, schemas_js_1.safeParse)(data, (v) => matcher.schema.parse(v), "Response validation failed");
            return [result.ok ? { ok: false, error: result.value } : result, raw];
        }
        else {
            return [
                (0, schemas_js_1.safeParse)(data, (v) => matcher.schema.parse(v), "Response validation failed"),
                raw,
            ];
        }
    };
}
const headerValRE = /, */;
/**
 * Iterates over a Headers object and returns an object with all the header
 * entries. Values are represented as an array to account for repeated headers.
 */
function unpackHeaders(headers) {
    const out = {};
    for (const [k, v] of headers.entries()) {
        out[k] = v.split(headerValRE);
    }
    return out;
}
/**
 * Discards the response body to free up resources.
 *
 * To learn why this is need, see the undici docs:
 * https://undici.nodejs.org/#/?id=garbage-collection
 */
async function discardResponseBody(res) {
    const reader = res.body?.getReader();
    if (reader == null) {
        return;
    }
    try {
        let done = false;
        while (!done) {
            const res = await reader.read();
            done = res.done;
        }
    }
    finally {
        reader.releaseLock();
    }
}
//# sourceMappingURL=matchers.js.map