/**
 * Shared utilities: response extraction and pagination helpers.
 */
import { ParseError } from './errors.js';
import { parseRateLimitHeaders } from './rate-limit.js';
export function extractRequestId(response) {
    return response.headers.get('x-request-id');
}
export function buildLastResponse(response) {
    return {
        requestId: extractRequestId(response),
        statusCode: response.status,
        headers: response.headers,
        rateLimit: parseRateLimitHeaders(response.headers),
    };
}
/**
 * Extracts the data payload from an openapi-fetch response.
 * Empty-body success responses return undefined; other empty responses throw.
 */
export function extractData(result, options = {}) {
    if (result.data !== undefined) {
        return attachResponseMetadata(result.data, result.response);
    }
    if (isEmptyBodySuccess(result.response) || options.allowEmptyBody) {
        return undefined;
    }
    // Degenerate openapi-fetch results with both data and error keep the SDK's
    // original data-first behavior; without data, errors stay fatal.
    if (result.error !== undefined) {
        throw new ParseError('Unexpected error response from API', JSON.stringify(result.error));
    }
    throw new ParseError('Unexpected empty response from API', result.response ? `status=${result.response.status}` : undefined);
}
export function withResponse(result, options = {}) {
    const data = extractData(result, options);
    const lastResponse = buildLastResponse(result.response);
    return {
        data,
        response: result.response,
        requestId: lastResponse.requestId,
        rateLimit: lastResponse.rateLimit,
    };
}
/**
 * Async iterator that auto-paginates through all pages.
 * Yields one item at a time.
 *
 * @example
 * for await (const agent of paginate((token) => client.agents.list({ continuation_token: token }))) {
 *   console.log(agent)
 * }
 */
export async function* paginate(fetcher) {
    let token = undefined;
    while (true) {
        const page = await fetcher(token);
        for (const item of page.items) {
            yield item;
        }
        if (!page.has_more || page.continuation_token === null)
            break;
        token = page.continuation_token;
    }
}
function attachResponseMetadata(data, response) {
    if (!response || typeof data !== 'object' || data === null) {
        return data;
    }
    const target = data;
    const lastResponse = buildLastResponse(response);
    defineHiddenMetadata(target, '_request_id', lastResponse.requestId);
    defineHiddenMetadata(target, 'lastResponse', lastResponse);
    return target;
}
function isEmptyBodySuccess(response) {
    return response?.status === 204 || response?.status === 205;
}
function defineHiddenMetadata(target, key, value) {
    try {
        Object.defineProperty(target, key, {
            value,
            enumerable: false,
            configurable: true,
            writable: false,
        });
    }
    catch {
        // Ignore non-extensible return values.
    }
}
//# sourceMappingURL=utils.js.map