import { ReadableStream as NodeReadableStream, TextEncoderStream, TransformStream, } from "node:stream/web";
import { HttpLink } from "@apollo/client/link/http";
const hasNextSymbol = Symbol("hasNext");
function mockIncrementalStream({ responseHeaders, }) {
    const CLOSE = Symbol();
    let streamController = null;
    let sentInitialChunk = false;
    const queue = [];
    function processQueue() {
        if (!streamController) {
            throw new Error("Cannot process queue without stream controller");
        }
        let chunk;
        while ((chunk = queue.shift())) {
            if (chunk === CLOSE) {
                streamController.close();
            }
            else {
                streamController.enqueue(chunk);
            }
        }
    }
    function createStream() {
        return new NodeReadableStream({
            start(c) {
                streamController = c;
                processQueue();
            },
        })
            .pipeThrough(new TransformStream({
            transform: (chunk, controller) => {
                controller.enqueue((!sentInitialChunk ? "\r\n---\r\n" : "") +
                    "content-type: application/json; charset=utf-8\r\n\r\n" +
                    JSON.stringify(chunk) +
                    (chunk[hasNextSymbol] ? "\r\n---\r\n" : "\r\n-----\r\n"));
                sentInitialChunk = true;
            },
        }))
            .pipeThrough(new TextEncoderStream());
    }
    const httpLink = new HttpLink({
        fetch(input, init) {
            return Promise.resolve(new Response(createStream(), {
                status: 200,
                headers: responseHeaders,
            }));
        },
    });
    function queueNext(event) {
        queue.push(event);
        if (streamController) {
            processQueue();
        }
    }
    function close() {
        queueNext(CLOSE);
        streamController = null;
        sentInitialChunk = false;
    }
    function enqueue(chunk, hasNext) {
        queueNext({ ...chunk, [hasNextSymbol]: hasNext });
        if (!hasNext) {
            close();
        }
    }
    return {
        httpLink,
        enqueue,
        close,
    };
}
export function mockDeferStream() {
    const { httpLink, enqueue } = mockIncrementalStream({
        responseHeaders: new Headers({
            "Content-Type": 'multipart/mixed; boundary="-"; deferSpec=20220824',
        }),
    });
    return {
        httpLink,
        enqueueInitialChunk(chunk) {
            enqueue(chunk, chunk.hasNext);
        },
        enqueueSubsequentChunk(chunk) {
            enqueue(chunk, chunk.hasNext);
        },
        enqueueErrorChunk(errors) {
            enqueue({
                hasNext: true,
                incremental: [
                    {
                        // eslint-disable-next-line @typescript-eslint/no-restricted-types
                        errors: errors,
                    },
                ],
            }, true);
        },
    };
}
export function mockMultipartSubscriptionStream() {
    const { httpLink, enqueue } = mockIncrementalStream({
        responseHeaders: new Headers({
            "Content-Type": "multipart/mixed",
        }),
    });
    enqueueHeartbeat();
    function enqueueHeartbeat() {
        enqueue({}, true);
    }
    return {
        httpLink,
        enqueueHeartbeat,
        enqueuePayloadResult(payload, hasNext = true) {
            enqueue({ payload }, hasNext);
        },
        enqueueProtocolErrors(errors) {
            enqueue({ payload: null, errors }, false);
        },
    };
}
//# sourceMappingURL=incremental.js.map
