"use strict";
/*
 * @adonisjs/core
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppKernel = void 0;
const application_1 = require("@adonisjs/application");
const utils_1 = require("../../utils");
const SignalsListener_1 = require("../SignalsListener");
/**
 * Kernel to manage application state
 */
class AppKernel {
    constructor(appRoot, environment) {
        /**
         * Find if the application has been booted or not
         */
        this.hasBooted = false;
        /**
         * Avoiding duplicate registeration of ts compiler hook
         */
        this.hasRegisteredTsHook = false;
        this.application = new application_1.Application(appRoot, environment);
        this.signalsListener = new SignalsListener_1.SignalsListener(this.application);
    }
    /**
     * Pretty prints a given error on the terminal
     */
    async prettyPrintError(error) {
        try {
            const Youch = require('youch');
            const output = await new Youch(error, {}).toJSON();
            console.log(require('youch-terminal')(output));
        }
        catch {
            console.log(error.stack);
        }
    }
    /**
     * Boot the application. The process for booting the app remains the
     * same regardless of the process environment.
     */
    async boot() {
        if (this.hasBooted) {
            return;
        }
        /**
         * Setting up the application.
         */
        await this.application.setup();
        /**
         * Registering providers
         */
        await this.application.registerProviders();
        /**
         * Booting providers
         */
        await this.application.bootProviders();
        /**
         * Importing preloaded files
         */
        await this.application.requirePreloads();
        this.hasBooted = true;
    }
    /**
     * Registers the TS compiler to hook into node require and
     * process TypeScript files
     */
    registerTsCompilerHook() {
        /**
         * Register ts hook when running typescript code directly
         */
        if (this.application.rcFile.typescript && !this.hasRegisteredTsHook) {
            this.hasRegisteredTsHook = true;
            (0, utils_1.registerTsHook)(this.application.appRoot);
        }
    }
    /**
     * Start the application. The callback is required to listen
     * for close signals
     */
    async start(shutdownCallback) {
        await this.application.start();
        this.signalsListener.listen(shutdownCallback || (() => this.close()));
        return () => this.close();
    }
    /**
     * Notify that process is ready
     */
    ready(eventPayload) {
        if (process.send) {
            process.send('ready');
            process.send({ isAdonisJS: true, environment: this.application.environment, ...eventPayload });
        }
    }
    /**
     * Prepare application for shutdown
     */
    async close() {
        this.signalsListener.cleanup();
        await this.application.shutdown();
    }
    /**
     * Handles ignitor boot errors
     */
    async handleError(error) {
        if (typeof error.handle === 'function') {
            await error.handle(error);
        }
        else if (this.application.inDev) {
            await this.prettyPrintError(error);
        }
        else {
            console.error(error.stack);
        }
    }
}
exports.AppKernel = AppKernel;
