"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SIGNAL_DIED = exports.SIGNAL_POSTMESSAGE = exports.SIGNAL_WAITING = void 0;
exports.syncFetch = syncFetch;
exports.buildTimeoutError = buildTimeoutError;
const node_worker_threads_1 = require("node:worker_threads");
const node_path_1 = require("node:path");
function syncFetch(url, options = {}, customOptions = {
    timeout: 30000
}) {
    const timeout = customOptions.timeout || 30000;
    const processingBuffer = 3000;
    const mainThreadTimeout = timeout + processingBuffer;
    const { port1, port2 } = new node_worker_threads_1.MessageChannel();
    const signalBuffer = new SharedArrayBuffer(8);
    const signalArray = new Int32Array(signalBuffer);
    const workerPath = customOptions._workerPath ?? (0, node_path_1.join)(__dirname, 'sync-fetch-worker.mjs');
    const worker = new node_worker_threads_1.Worker(workerPath, {
        name: 'sync-fetch',
        eval: false,
        workerData: {
            url,
            options,
            timeout,
            port: port2,
            signalBuffer
        },
        transferList: [port2]
    });
    worker.on('error', () => {
    });
    performance.mark('axe-watcher:sync-fetch:start');
    let message;
    try {
        Atomics.wait(signalArray, 0, 0, mainThreadTimeout);
        message = (0, node_worker_threads_1.receiveMessageOnPort)(port1);
        if (message === undefined) {
            throw buildTimeoutError({
                mainThreadTimeout,
                wakeReason: Atomics.load(signalArray, 0),
                exitCode: Atomics.load(signalArray, 1)
            });
        }
        const { data, error } = message.message;
        if (error) {
            const syncErr = new Error('Sync Fetch Failed');
            syncErr.cause = error;
            throw syncErr;
        }
        return data;
    }
    finally {
        performance.mark('axe-watcher:sync-fetch:end');
        port1.close();
        worker.terminate();
        const clone = structuredClone(options);
        clone.headers = sanitizeHeaders(clone.headers);
        performance.measure('axe-watcher:sync-fetch', {
            start: 'axe-watcher:sync-fetch:start',
            end: 'axe-watcher:sync-fetch:end',
            detail: {
                url,
                options: clone,
                timeout,
                status: message?.message.type || 'no-response',
                response: {
                    status: message?.message.data?.status,
                    statusText: message?.message.data?.statusText
                }
            }
        });
    }
}
exports.SIGNAL_WAITING = 0;
exports.SIGNAL_POSTMESSAGE = 1;
exports.SIGNAL_DIED = 2;
function buildTimeoutError(args) {
    const { mainThreadTimeout, wakeReason, exitCode } = args;
    const reason = wakeReason === exports.SIGNAL_DIED
        ? `worker exited with code ${exitCode} before responding`
        : `worker thread did not respond within ${mainThreadTimeout}ms`;
    return new Error(`Request timed out - ${reason}`);
}
function sanitizeHeaders(headers) {
    if (!headers) {
        return undefined;
    }
    const sanitized = {};
    for (const [key, value] of Object.entries(headers)) {
        if (key.toLowerCase() === 'x-api-key'.toLowerCase()) {
            sanitized[key.toLowerCase()] = 'REDACTED';
            continue;
        }
        sanitized[key.toLowerCase()] = value;
    }
    return sanitized;
}
//# sourceMappingURL=sync-fetch.js.map