"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OrmClient = exports.GraphQLRequestError = exports.FetchAdapter = void 0;
const runtime_1 = require("@constructive-io/graphql-query/runtime");
/**
 * Default adapter that uses fetch for HTTP requests.
 *
 * When no custom fetch is provided, uses @constructive-io/fetch which
 * handles *.localhost DNS rewriting and Host header preservation in
 * Node.js. Pass a custom fetch to override for test mocking or custom
 * proxy/credentials.
 */
class FetchAdapter {
    endpoint;
    headers;
    fetchFn;
    constructor(endpoint, headers, fetchFn) {
        this.endpoint = endpoint;
        this.headers = headers ?? {};
        this.fetchFn = fetchFn ?? (0, runtime_1.createFetch)();
    }
    async execute(document, variables) {
        const response = await this.fetchFn(this.endpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                ...this.headers,
            },
            body: JSON.stringify({
                query: document,
                variables: variables ?? {},
            }),
        });
        if (!response.ok) {
            return {
                ok: false,
                data: null,
                errors: [{ message: `HTTP ${response.status}: ${response.statusText}` }],
            };
        }
        const json = (await response.json());
        if (json.errors && json.errors.length > 0) {
            return {
                ok: false,
                data: null,
                errors: json.errors,
            };
        }
        return {
            ok: true,
            data: json.data,
            errors: undefined,
        };
    }
    setHeaders(headers) {
        this.headers = { ...this.headers, ...headers };
    }
    getEndpoint() {
        return this.endpoint;
    }
}
exports.FetchAdapter = FetchAdapter;
/**
 * Error thrown when GraphQL request fails
 */
class GraphQLRequestError extends Error {
    errors;
    data;
    constructor(errors, data = null) {
        const messages = errors.map((e) => e.message).join('; ');
        super(`GraphQL Error: ${messages}`);
        this.errors = errors;
        this.data = data;
        this.name = 'GraphQLRequestError';
    }
}
exports.GraphQLRequestError = GraphQLRequestError;
class OrmClient {
    adapter;
    constructor(config) {
        if (config.adapter) {
            this.adapter = config.adapter;
        }
        else if (config.endpoint) {
            this.adapter = new FetchAdapter(config.endpoint, config.headers, config.fetch);
        }
        else {
            throw new Error('OrmClientConfig requires either an endpoint or a custom adapter');
        }
    }
    async execute(document, variables) {
        return this.adapter.execute(document, variables);
    }
    /**
     * Set headers for requests.
     * Only works if the adapter supports headers.
     */
    setHeaders(headers) {
        if (this.adapter.setHeaders) {
            this.adapter.setHeaders(headers);
        }
    }
    /**
     * Get the endpoint URL.
     * Returns empty string if the adapter doesn't have an endpoint.
     */
    getEndpoint() {
        return this.adapter.getEndpoint?.() ?? '';
    }
}
exports.OrmClient = OrmClient;
