<commit_before>import { Subject } from 'rxjs';
import React from 'react';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import _ from 'lodash';

import createAppendActionMiddleware from './middlewares/appendAction';
import Provider from './components/Provider';

class BaseApp {
  constructor(opts = {}) {
    this.options = {
      // primary info
      name: 'App',
      appId: null,
      devSessionId: null,
      rootApp: null,
      version: 1,

      // the root component to render
      component: null,

      // list of Model instances
      models: {},

      // store
      store: null,
      reducer: (state = {}) => state,
      initialState: {},

      services: {},
      factories: {},

      // lifecycle callbacks
      beforeMount: () => {},
      afterMount: () => {},
      beforeUnmount: () => {},

      // override
      ...opts
    };

    if (!this.options.appId) {
      throw new Error('Must provide `appId` in options');
    }

    if (!this.options.component) {
      throw new Error('Must provide `component` in options');
    }

    this.widgetsByRegion = {};

    if (typeof window.app !== 'undefined') {
      this.options.rootApp = window.app;
    }

    this.widgetsSubject = new Subject();

    this.createStore(
      this.options.reducer,
      this.options.initialState
    );

    this.readableApps = [];
  }

  getRootApp() {
    return this.options.rootApp;
  }

  getModel(modelName) { // eslint-disable-line
    // will be implemented below when extended
  }

  getService(serviceName) { // eslint-disable-line
    // will be implemented below when extended
  }

  getFactory(factoryName) {
    // TODO: optimize code to be more DRY
    const factories = this.getOption('factories');
    const FactoryClass = factories[factoryName];

    if (FactoryClass) {
      return new FactoryClass({
        app: this
      });
    }

    const rootApp = this.getRootApp();

    if (!rootApp) {
      return null;
    }

    const rootFactories = rootApp.getOption('factories');
    const RootFactoryClass = rootFactories[factoryName];

    if (RootFactoryClass) {
      return new RootFactoryClass({
        app: this
      });
    }

    return null;
  }

  createStore(rootReducer, initialState = {}) {
    this.options.store = createStore(
      rootReducer,
      initialState,
      compose(
        applyMiddleware(
          thunk.withExtraArgument({ app: this }),
          createAppendActionMiddleware({
            key: 'appName',
            value: this.getOption('name')
          }),
          createLogger() // @TODO: load it in DEV environment only
        )
      )
    );<commit_msg>do not load logger in production mode (#26)<commit_after>import { Subject } from 'rxjs';
import React from 'react';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import _ from 'lodash';

import createAppendActionMiddleware from './middlewares/appendAction';
import Provider from './components/Provider';

class BaseApp {
  constructor(opts = {}) {
    this.options = {
      // primary info
      name: 'App',
      appId: null,
      devSessionId: null,
      rootApp: null,
      version: 1,

      // the root component to render
      component: null,

      // list of Model instances
      models: {},

      // store
      store: null,
      reducer: (state = {}) => state,
      initialState: {},

      services: {},
      factories: {},

      // lifecycle callbacks
      beforeMount: () => {},
      afterMount: () => {},
      beforeUnmount: () => {},

      // override
      ...opts
    };

    if (!this.options.appId) {
      throw new Error('Must provide `appId` in options');
    }

    if (!this.options.component) {
      throw new Error('Must provide `component` in options');
    }

    this.widgetsByRegion = {};

    if (typeof window.app !== 'undefined') {
      this.options.rootApp = window.app;
    }

    this.widgetsSubject = new Subject();

    this.createStore(
      this.options.reducer,
      this.options.initialState
    );

    this.readableApps = [];
  }

  getRootApp() {
    return this.options.rootApp;
  }

  getModel(modelName) { // eslint-disable-line
    // will be implemented below when extended
  }

  getService(serviceName) { // eslint-disable-line
    // will be implemented below when extended
  }

  getFactory(factoryName) {
    // TODO: optimize code to be more DRY
    const factories = this.getOption('factories');
    const FactoryClass = factories[factoryName];

    if (FactoryClass) {
      return new FactoryClass({
        app: this
      });
    }

    const rootApp = this.getRootApp();

    if (!rootApp) {
      return null;
    }

    const rootFactories = rootApp.getOption('factories');
    const RootFactoryClass = rootFactories[factoryName];

    if (RootFactoryClass) {
      return new RootFactoryClass({
        app: this
      });
    }

    return null;
  }

  createStore(rootReducer, initialState = {}) {
    const middlewares = [
      thunk.withExtraArgument({ app: this }),
      createAppendActionMiddleware({
        key: 'appName',
        value: this.getOption('name')
      })
    ];

    if (process.env.NODE_ENV !== 'production') {
      const createLogger = require('redux-logger');

      middlewares.push(createLogger());
    }

    this.options.store = createStore(
      rootReducer,
      initialState,
      compose(
        applyMiddleware(...middlewares)
      )
    );
{'fraction_non_alphanumeric': 0.12524779239502612, 'fraction_numerical': 0.0007208506037123806, 'mean_word_length': 2.3373421527360194, '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': '2175684', 'n_tokens_mistral': 1645, 'n_tokens_neox': 1581, 'n_words': 394}