"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProcessRepository = void 0;
const common_1 = require("@nestjs/common");
const node_child_process_1 = require("node:child_process");
const node_stream_1 = require("node:stream");
let ProcessRepository = class ProcessRepository {
    spawn = node_child_process_1.spawn;
    spawnDuplexStream(command, args, options) {
        let stdinClosed = false;
        let drainCallback;
        const process = this.spawn(command, args, options);
        const duplex = new node_stream_1.Duplex({
            write(chunk, encoding, callback) {
                if (stdinClosed) {
                    return callback();
                }
                if (process.stdin.write(chunk, encoding)) {
                    callback();
                }
                else {
                    drainCallback = callback;
                    process.stdin.once('drain', () => {
                        drainCallback = undefined;
                        callback();
                    });
                }
            },
            read() {
            },
            final(callback) {
                if (stdinClosed) {
                    callback();
                }
                else {
                    process.stdin.end(callback);
                }
            },
        });
        process.stdout.on('data', (chunk) => {
            if (!duplex.push(chunk)) {
                process.stdout.pause();
            }
        });
        duplex.on('resume', () => process.stdout.resume());
        let stdoutClosed = false;
        function close(error) {
            stdinClosed = true;
            if (error) {
                duplex.destroy(error);
            }
            else if (stdoutClosed && typeof process.exitCode === 'number') {
                duplex.push(null);
            }
        }
        process.stdout.on('close', () => {
            stdoutClosed = true;
            close();
        });
        process.on('error', close);
        process.stdout.on('error', close);
        process.stdin.on('error', (error) => {
            if (error?.code === 'EPIPE') {
                try {
                    drainCallback();
                }
                catch (error) {
                    close(error);
                }
            }
            else {
                close(error);
            }
        });
        let stderr = '';
        process.stderr.on('data', (chunk) => (stderr += chunk));
        process.on('exit', (code) => {
            console.info(`${command} exited (${code})`);
            if (code === 0) {
                close();
            }
            else {
                close(new Error(`${command} non-zero exit code (${code})\n${stderr}`));
            }
        });
        return Object.assign(duplex, { _process: process });
    }
    fork(...args) {
        return (0, node_child_process_1.fork)(...args);
    }
};
exports.ProcessRepository = ProcessRepository;
exports.ProcessRepository = ProcessRepository = __decorate([
    (0, common_1.Injectable)()
], ProcessRepository);
//# sourceMappingURL=process.repository.js.map