"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RunScriptWebpackPlugin = void 0;
const child_process_1 = require("child_process");
function getSignal(signal) {
    // allow users to disable sending a signal by setting to `false`...
    if (signal === false)
        return;
    if (signal === true)
        return 'SIGUSR2';
    return signal;
}
class RunScriptWebpackPlugin {
    constructor(options = {}) {
        this.afterEmit = (compilation, cb) => {
            var _a;
            if (this.worker && this.worker.connected && ((_a = this.worker) === null || _a === void 0 ? void 0 : _a.pid)) {
                if (this.options.autoRestart) {
                    this._restartServer();
                    cb();
                    return;
                }
                const signal = getSignal(this.options.signal);
                if (signal) {
                    process.kill(this.worker.pid, signal);
                }
                cb();
                return;
            }
            this.startServer(compilation, cb);
        };
        this.apply = (compiler) => {
            compiler.hooks.afterEmit.tapAsync({ name: 'RunScriptPlugin' }, this.afterEmit);
        };
        this.startServer = (compilation, cb) => {
            const { assets, compiler } = compilation;
            const { options } = this;
            let name;
            const names = Object.keys(assets);
            if (options.name) {
                name = options.name;
                if (!assets[name]) {
                    console.error(`Entry ${name} not found. Try one of: ${names.join(' ')}`);
                }
            }
            else {
                name = names[0];
                if (names.length > 1) {
                    console.log(`More than one entry built, selected ${name}. All names: ${names.join(' ')}`);
                }
            }
            if (!compiler.options.output || !compiler.options.output.path) {
                throw new Error('output.path should be defined in webpack config!');
            }
            this._entrypoint = `${compiler.options.output.path}/${name}`;
            this._startServer((worker) => {
                this.worker = worker;
                cb();
            });
        };
        this.options = {
            autoRestart: true,
            signal: false,
            // Only listen on keyboard in development, so the server doesn't hang forever
            keyboard: process.env.NODE_ENV === 'development',
            ...options,
            args: [...(options.args || [])],
            nodeArgs: options.nodeArgs || process.execArgv,
        };
        if (this.options.restartable) {
            this._enableRestarting();
        }
    }
    _enableRestarting() {
        if (this.options.keyboard) {
            process.stdin.setEncoding('utf8');
            process.stdin.on('data', (data) => {
                if (data.trim() === 'rs') {
                    this._restartServer();
                }
            });
        }
    }
    _restartServer() {
        var _a;
        console.log('Restarting app...');
        if ((_a = this.worker) === null || _a === void 0 ? void 0 : _a.pid) {
            const signal = getSignal(this.options.signal);
            process.kill(this.worker.pid, signal);
        }
        this._startServer((worker) => {
            this.worker = worker;
        });
    }
    _startServer(cb) {
        const { args, nodeArgs, cwd, env } = this.options;
        if (!this._entrypoint)
            throw new Error('run-script-webpack-plugin requires an entrypoint.');
        const child = (0, child_process_1.fork)(this._entrypoint, args, {
            execArgv: nodeArgs,
            stdio: 'inherit',
            cwd,
            env,
        });
        setTimeout(() => cb(child), 0);
    }
}
exports.RunScriptWebpackPlugin = RunScriptWebpackPlugin;
