import { createInterface } from 'node:readline';
import fetch from 'node-fetch';
export class Watch {
    constructor(config) {
        this.config = config;
    }
    // Watch the resource and call provided callback with parsed json object
    // upon event received over the watcher connection.
    //
    // "done" callback is called either when connection is closed or when there
    // is an error. In either case, watcher takes care of properly closing the
    // underlaying connection so that it doesn't leak any resources.
    async watch(path, queryParams, callback, done) {
        const cluster = this.config.getCurrentCluster();
        if (!cluster) {
            throw new Error('No currently active cluster');
        }
        const watchURL = new URL(cluster.server + path);
        watchURL.searchParams.set('watch', 'true');
        for (const [key, val] of Object.entries(queryParams || {})) {
            if (val !== undefined) {
                watchURL.searchParams.set(key, val.toString());
            }
        }
        const requestInit = await this.config.applyToFetchOptions({});
        const controller = new AbortController();
        requestInit.signal = controller.signal;
        requestInit.method = 'GET';
        let doneCalled = false;
        const doneCallOnce = (err) => {
            if (!doneCalled) {
                controller.abort();
                doneCalled = true;
                done(err);
            }
        };
        try {
            const response = await fetch(watchURL, requestInit);
            if (response.status === 200) {
                response.body.on('error', doneCallOnce);
                response.body.on('close', () => doneCallOnce(null));
                response.body.on('finish', () => doneCallOnce(null));
                const lines = createInterface(response.body);
                lines.on('error', doneCallOnce);
                lines.on('close', () => doneCallOnce(null));
                lines.on('finish', () => doneCallOnce(null));
                lines.on('line', (line) => {
                    try {
                        const data = JSON.parse(line.toString());
                        callback(data.type, data.object, data);
                    }
                    catch (ignore) {
                        // ignore parse errors
                    }
                });
            }
            else {
                const error = new Error(response.statusText);
                error.statusCode = response.status;
                throw error;
            }
        }
        catch (err) {
            doneCallOnce(err);
        }
        return controller;
    }
}
Watch.SERVER_SIDE_CLOSE = { error: 'Connection closed on server' };
//# sourceMappingURL=watch.js.map