<commit_before>/**
 * Base application
 * @module arpen/app/base
 */
const debug = require('debug')('arpen:app');
const fs = require('fs-ext');
const path = require('path');
const merge = require('merge');
const WError = require('verror').WError;
const ErrorHelper = require('../services/error.js');
const Filer = require('../services/filer.js');

/**
 * Base application class
 */
class App {
    /**
     * Create app
     * @param {string} basePath             Base path
     * @param {string[]} argv               Arguments
     */
    constructor(basePath, argv) {
        debug('Constructing the app');
        this.basePath = basePath;
        this.argv = argv;

        this._initialized = null;
        this._running = null;
        this._container = new Map();

        this.registerInstance(this, 'app');
    }

    /**
     * Graceful shutdown timeout
     * @type {number}
     */
    static get gracefulTimeout() {
        return 10 * 1000; // ms
    }

    /**
     * Register an instance of a service
     * @param {*} instance                  Instance
     * @param {string} name                 Name
     * @return {string}                     Returns name of the service
     */
    registerInstance(instance, name) {
        if (!name)
            throw new Error('No name provided for an instance');

        debug(`Registering instance '${name}'`);
        let service = this._initService(name);
        service.instance = instance;

        return service.provides;
    }

    /**
     * Register class function as a service
     * @param {function} classFunc          Class function
     * @param {string} [filename]           Path to the file
     * @return {string}                     Returns name of the service
     */
    registerClass(classFunc, filename) {
        let name = classFunc.provides;
        if (!name)
            throw new Error('No name provided for a class');

        debug(`Registering class '${name}'`);
        let service = this._initService(name, filename);
        service.class = classFunc;
        service.requires = classFunc.requires || [];

        return service.provides;
    }

    /**
     * Check if service is registered
     * @param {string} name                 Service name
     * @return {boolean}
     */
    has(name) {
        if (!name)
            throw new Error('No service name provided');

        return this._container.has(name);
    }

    /**
     * Get instance of a service
     * @param {string} name                 Service name
     * @param {...*} extra                  Optional extra arguments to the constructor
     * @return {object}                     Returns instance
     */
    get(name, ...extra) {
        if (!name)
            throw new Error('No service name provided');

        debug(`Retrieving service '${name}'`);
        return this._resolveService(name, extra, new Map());
    }

    /**
     * Search registered services
     * @param {RegExp} re                   Service name RegExp
     * @return {string[]}                   Returns array of matching service names
     */
    search(re) {
        debug(`Searching for services ${re}`);
        let result = [];
        for (let name of this._container.keys()) {
            if (re.test(name))
                result.push(name);
        }
        return result;
    }

    /**
     * Debug output
     * @param {...*} messages                           Messages
     */
    debug(...messages) {
        if (!(!!process.env.DEBUG))
            return Promise.resolve();

        return this._output(process.stderr, messages);
    }

    /**
     * Info output
     * @param {...*} messages                           Messages
     */
    info(...messages) {
        return this._output(process.stdout, messages);
    }

    /**
     * Error output
     * @param {...*} messages                           Messages
     */
    error(...messages) {
        return this._output(process.stderr, messages);
    }

    /**
     * Run the app. This method will simply call .init() and then .start().
     * @param {object} options                          Arpen options
     * @param {boolean} [options.disableServicesCache]  When true services cache will not be used
     * @param {boolean} [options.disableLogFiles]       When true log files will not be used
     * @param {...*} args                               Descendant-specific arguments
     */
    run(options, ...args) {
        this.init(options, ...args)
            .then(() => {
                return this.start(options, ...args);
            })
            .catch(error => {
                let msg = (error.stack ? error.stack : error.message);

                try {
                    let errService = new ErrorHelper();
                    if (error instanceof WError || (error.constructor && error.constructor.name === 'WError')) {
                        msg = '\nException data: ' + JSON.stringify(errService.info(error), undefined, 4);
                        for (let err of errService.flatten(error))
                            msg += '\n' + (err.stack ? err.stack : err.message);
                    }
                } catch (error) {
                    // do nothing
                }

                return this.error('App.run() failed:', msg)
                    .then(() => {
                        process.exit(1);
                    });
            });
    }

    /**
     * Initialize the app
     * @param {object} options                          App.run() options
     * @param {...*} args                               Descendant-specific arguments
     * @return {Promise}
     */
    init(options, ...args) {
        if (this._initialized)
            return Promise.resolve();

        debug('Initializing the app');
        let onSignal = signal => {
            if (typeof this.onSignal === 'function')<commit_msg>Reset error msg in app.run()<commit_after>/**
 * Base application
 * @module arpen/app/base
 */
const debug = require('debug')('arpen:app');
const fs = require('fs-ext');
const path = require('path');
const merge = require('merge');
const WError = require('verror').WError;
const ErrorHelper = require('../services/error.js');
const Filer = require('../services/filer.js');

/**
 * Base application class
 */
class App {
    /**
     * Create app
     * @param {string} basePath             Base path
     * @param {string[]} argv               Arguments
     */
    constructor(basePath, argv) {
        debug('Constructing the app');
        this.basePath = basePath;
        this.argv = argv;

        this._initialized = null;
        this._running = null;
        this._container = new Map();

        this.registerInstance(this, 'app');
    }

    /**
     * Graceful shutdown timeout
     * @type {number}
     */
    static get gracefulTimeout() {
        return 10 * 1000; // ms
    }

    /**
     * Register an instance of a service
     * @param {*} instance                  Instance
     * @param {string} name                 Name
     * @return {string}                     Returns name of the service
     */
    registerInstance(instance, name) {
        if (!name)
            throw new Error('No name provided for an instance');

        debug(`Registering instance '${name}'`);
        let service = this._initService(name);
        service.instance = instance;

        return service.provides;
    }

    /**
     * Register class function as a service
     * @param {function} classFunc          Class function
     * @param {string} [filename]           Path to the file
     * @return {string}                     Returns name of the service
     */
    registerClass(classFunc, filename) {
        let name = classFunc.provides;
        if (!name)
            throw new Error('No name provided for a class');

        debug(`Registering class '${name}'`);
        let service = this._initService(name, filename);
        service.class = classFunc;
        service.requires = classFunc.requires || [];

        return service.provides;
    }

    /**
     * Check if service is registered
     * @param {string} name                 Service name
     * @return {boolean}
     */
    has(name) {
        if (!name)
            throw new Error('No service name provided');

        return this._container.has(name);
    }

    /**
     * Get instance of a service
     * @param {string} name                 Service name
     * @param {...*} extra                  Optional extra arguments to the constructor
     * @return {object}                     Returns instance
     */
    get(name, ...extra) {
        if (!name)
            throw new Error('No service name provided');

        debug(`Retrieving service '${name}'`);
        return this._resolveService(name, extra, new Map());
    }

    /**
     * Search registered services
     * @param {RegExp} re                   Service name RegExp
     * @return {string[]}                   Returns array of matching service names
     */
    search(re) {
        debug(`Searching for services ${re}`);
        let result = [];
        for (let name of this._container.keys()) {
            if (re.test(name))
                result.push(name);
        }
        return result;
    }

    /**
     * Debug output
     * @param {...*} messages                           Messages
     */
    debug(...messages) {
        if (!(!!process.env.DEBUG))
            return Promise.resolve();

        return this._output(process.stderr, messages);
    }

    /**
     * Info output
     * @param {...*} messages                           Messages
     */
    info(...messages) {
        return this._output(process.stdout, messages);
    }

    /**
     * Error output
     * @param {...*} messages                           Messages
     */
    error(...messages) {
        return this._output(process.stderr, messages);
    }

    /**
     * Run the app. This method will simply call .init() and then .start().
     * @param {object} options                          Arpen options
     * @param {boolean} [options.disableServicesCache]  When true services cache will not be used
     * @param {boolean} [options.disableLogFiles]       When true log files will not be used
     * @param {...*} args                               Descendant-specific arguments
     */
    run(options, ...args) {
        this.init(options, ...args)
            .then(() => {
                return this.start(options, ...args);
            })
            .catch(error => {
                let msg;

                try {
                    let errService = new ErrorHelper();
                    if (error instanceof WError || (error.constructor && error.constructor.name === 'WError')) {
                        msg = '\nException data: ' + JSON.stringify(errService.info(error), undefined, 4);
                        for (let err of errService.flatten(error))
                            msg += '\n' + (err.stack ? err.stack : err.message);
                    }
                } catch (error) {
                    msg = (error.stack ? error.stack : error.message);
                }

                return this.error('App.run() failed:', msg)
                    .then(() => {
                        process.exit(1);
                    });
            });
    }

    /**
     * Initialize the app
     * @param {object} options                          App.run() options
     * @param {...*} args                               Descendant-specific arguments
     * @return {Promise}
     */
    init(options, ...args) {
        if (this._initialized)
            return Promise.resolve();

        debug('Initializing the app');
        let onSignal = signal => {
            if (typeof this.onSignal === 'function')
{'fraction_non_alphanumeric': 0.12438318870171856, 'fraction_numerical': 0.00136123872724179, 'mean_word_length': 1.502128565346956, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '179786', 'n_tokens_mistral': 3025, 'n_tokens_neox': 2916, 'n_words': 842}