<commit_before>var config = require('./config');
var mongoOp = require('./model/mongo');
var logging = require('./logging');
var stringProcessor = require('./stringprocessor');

function addReminder(inputText, familyId, callback) {
	var sendTo = stringProcessor.getFirstWord(inputText);
	var dateText = stringProcessor.removeFirstWord(sendTo);
	mongoOp.FamilyMembers.findOne({'name': sendTo, 'familyId':familyId}, function (err, familyMember) {
		if (familyMember == null) {
			callback('@' + sendTo + ' unkown sorry! 😕')
		} else {
			var sendToId = familyMember.userId

			//check lists and create if necessary
			mongoOp.Lists.findOne({'listKey': config.remindersListKey, 'familyId':familyId}, function(err, list) {
				if (list == null) {
					var newList = new mongoOp.Lists({
						"listKey" : config.remindersListKey,
						"listDescription" : config.remindersListKey,
						"familyId" : familyId
					});
					newList.save(function (err, data) {
						if (err) callback('Error creating reminder list 😦');
					});
				}

				//create listItem
				var newItem = new mongoOp.ListItems({
					"listKey" : config.remindersListKey,
					"listItemName" : "Remind: @" + inputText,
					"familyId" : familyId,
					"reminderWhen": new Date(dateText),
					"reminderUserId": sendToId
				});
				newItem.save(function (err, data) {
					if (err) callback('Error adding reminder 😦');
					else {
						console.log('----reminder saved: ' + inputText + ' Date:' + new Date(dateText) + ' < ' + dateText);
						callback(null)
					}
				});
			});
		}
	});
}

module.exports = {
	addReminder
}<commit_msg>scheduler<commit_after>var config = require('./config');
var mongoOp = require('./model/mongo');
var logging = require('./logging');
var stringProcessor = require('./stringprocessor');

function addReminder(inputText, familyId, callback) {
	var sendTo = stringProcessor.getFirstWord(inputText);
	var dateText = stringProcessor.removeFirstWord(inputText);
	mongoOp.FamilyMembers.findOne({'name': sendTo, 'familyId':familyId}, function (err, familyMember) {
		if (familyMember == null) {
			callback('@' + sendTo + ' unkown sorry! 😕')
		} else {
			var sendToId = familyMember.userId

			//check lists and create if necessary
			mongoOp.Lists.findOne({'listKey': config.remindersListKey, 'familyId':familyId}, function(err, list) {
				if (list == null) {
					var newList = new mongoOp.Lists({
						"listKey" : config.remindersListKey,
						"listDescription" : config.remindersListKey,
						"familyId" : familyId
					});
					newList.save(function (err, data) {
						if (err) callback('Error creating reminder list 😦');
					});
				}

				//create listItem
				var newItem = new mongoOp.ListItems({
					"listKey" : config.remindersListKey,
					"listItemName" : "Remind: @" + inputText,
					"familyId" : familyId,
					"reminderWhen": new Date(dateText),
					"reminderUserId": sendToId
				});
				newItem.save(function (err, data) {
					if (err) callback('Error adding reminder 😦');
					else {
						console.log('----reminder saved: ' + inputText + ' Date:' + new Date(dateText) + ' < ' + dateText);
						callback(null)
					}
				});
			});
		}
	});
}

module.exports = {
	addReminder
}<|endoftext|>


<commit_before>var _ = require('lodash');
var parallel = require('when/parallel');
var sequence = require('when/sequence');
var Promises = require('backbone-promises');
var when = Promises.when;
var PromisedModel = Promises.Model;
var Backbone = require('backbone');
var SchemaModel = require('backbone-blueprint').ValidatingModel;
var ValidationError = require('../errors').ValidationError;
var logId = 'serverbone:models:base';
var _debug = require('debug');
var when = Promises.when;

var debug = {
  trace: _debug(logId + ':trace'),
  log: _debug(logId + ':log'),
  warn: _debug(logId + ':warn'),
  error: _debug(logId + ':error')
};

/**
 * Format 'templated' properties of object like {type: '{type}'}
 * using given this-context for the actual value
 * @param  {Object} properties
 * @return {Object}
 */
var formatProperties = function(properties) {
  var self = this;
  var realProperties = {};

  function getTemplateValue(property) {
    function getThisValue(match) {
      var cleanedValue = match.substring(1, match.length - 1);
      return self[cleanedValue];
    }
    return property.replace(/{([^}]+)}+/g, getThisValue);
  }

  for (var propertyKey in properties) {
    realProperties[propertyKey] = getTemplateValue(properties[propertyKey]);
  }

  return realProperties;
};

// convert error & reject
var failWithError = function(options, err) {
  options = options || {};
  if (options.ignoreFailures) return Promises.when.resolve();
  return when.reject(err);
};

var BaseModel = SchemaModel.extend({
  initialize: function(attributes, options) {
    //debug.trace('BaseModel.initialize');
    BaseModel.__super__.initialize.apply(this, [attributes, options]);
    this.options = options ? _.clone(options) : {};
    this._processSchema();
    // attributes which have changed since this model was synced
    this._changedSinceSync = {};
    // attributes which this model had when last synced
    this._attributesOnSync = false;
    this.on('change', this.attributesChanged, this);
    this.on('sync', this.modelSynced, this);
  },

  _processSchema: function() {
    if (!this.schema) return;
    this.indexes = this.schema.indexes;
  },

  url: function() {
    var key = this.dbBaseKey || this.type;
    if (this.isNew()) {
      return key;
    } else {
      return key + ':' + this.get(this.idAttribute);
    }
  },

  sync: function() {
    throw new Error('sync method should be overridden!');
  },

  save: function(key, val, options) {
    var opts = options || {};
    var self = this;
    if (key == null || typeof key === 'object') {
      opts = val || {};
    }
    var error = opts.error;
    var fns = [
      _.bind(self.preSave, self, opts),
      _.bind(PromisedModel.prototype.save, self, key, opts),
      _.bind(self.afterSave, self, opts)
    ];
    return sequence(fns).then(function(results) {
      return results[1];
    }, function(err) {
      if (error) error.call(opts, self, err);
      return failWithError(opts, err);
    });
  },

  fetch: function(options) {
    var self = this;

    options = options || {};

    var error = options.error;

    var fns = [
      _.bind(self.preFetch, self, options),
      _.bind(PromisedModel.prototype.fetch, self, options),
      _.bind(self.afterFetch, self, options)
    ];

    return sequence(fns).then(function () {
      self.fetchStatus = 'fetched';
      return self;
    }, function (err) {
      if (error) error.call(options, self, err);
      return failWithError(options, err);
    });
  },

  destroy: function(options) {
    options =  options || {};
    var fns = [
      _.bind(this.preDelete, this, _.clone(options)),
      _.bind(PromisedModel.prototype.destroy, this, options),
      _.bind(this.afterDelete, this, options)
    ];
    return sequence(fns)
      .then(function(results) {
        return results[1];
      }, _.bind(failWithError, null, options));
  },

  // stub, everyone can access
  canAccess: function() {
    return true;
  },

  //TODO: this is just a dummy method, should be implemented
  getRoles: function() {
    var roles = [];
    return roles;
  },

  // Field level access: get properties which user has permissions
  // field can override object level access mask
  propertiesWithAccess: function() {
    return Object.keys(this.schema.properties);
  },

  toJSON: function(options) {
    options = options || {};
    var json = BaseModel.__super__.toJSON.apply(this, arguments);
    return json;
  },

  validate: function(attrs, options) {
    options = options || {};
    var validationErrors = BaseModel.__super__.validate.apply(this, arguments);
    if (validationErrors) return new ValidationError({
      errors: validationErrors
    });
  },

  /**
   * Fetch current model & its relations
   * Need to fetch current model first in order to apply correct ids to relations
   */
  fetchAll: function(options) {
    debug.trace('fetchAll %s',JSON.stringify(options));
    options = options || {};
    options.action = options.action || 'read';
    var self = this;
    var when = Promises.when;
    options.action = 'read';
    function handleError(err) {
      if (options.ignoreFailures) {
        return when.resolve(self);
      } else {
        return when.reject(err);
      }
    }
    return this
      .fetch(options)
      .then(function() {
        if (!self.relationDefinitions) {
          return self;
        }
        return self
          .fetchRelations(options)
          .then(function() {
            return self;
          }, handleError);
      }, handleError);
  },

  /**
   * Fetches relations available based on current attributes
   * if options.onlyRelations Array is specified only those relations are fetched
   * e.g. fetchRelations({onlyRelations: ['user']}) will fetch only relation 'user'
   */
  fetchRelations: function(options) {
    options = options || {};
    var when = Promises.when;
    var self = this;
    var fns = [];
    _.each(self.relationDefinitions, function(relationAttributes, relationKey) {
      if (_.isArray(options.onlyRelations)) {
        if (options.onlyRelations.indexOf(relationKey) === -1) return;
      }
      var relation = self.get(relationKey);
      if (relation && !relation.url) {
        return;
      }
      if (relation && relation.fetch) {
        // When the run is parallel, clone the options so no shared promises happen.
        fns.push(_.bind(relation.fetch, relation, _.clone(options)));
      }
    }, this);

    return parallel(fns)
      .then(function relationsFetched() {
        self.fetchStatus = 'all_fetched';
        return self;
      }, function error(err) {
        if (options.ignoreFailures) {
          self.fetchStatus = 'all_fetched';
          return when.resolve(self);
        }
        return when.reject(err);
      });
  },

  /**
   * Fetch model/relations based on given projection.
   * Tries to avoid unnecessary fetches.
   * TODO: this does not support all projection options yet.
   * @param  {object} projection
   * @param  {object} options
   * @return {Promise}
   */
  fetchRequired: function(projection, options) {
    var requiredProperties = projection.onlyFields;
    var fetchRequired = _.any(requiredProperties, function(prop) {
      return this.get(prop) === undefined;
    }, this);

    var relationsToBeFetched = [];
    var relations = _.omit(projection, 'onlyFields', 'removeFields');
    _.each(relations, function(attrs, relKey) {
      var r = this.get(relKey);
      var missingKeys = _.any(attrs, function(attr) {
        return r && r.get && r.get(attr) === undefined;
      });
      if (!r || missingKeys) relationsToBeFetched.push(relKey);
    }, this);

    if (relationsToBeFetched.length) fetchRequired = true;

    if (!fetchRequired) {
      return when.resolve();
    }
    if (relationsToBeFetched.length) {
      return this.fetchAll({onlyRelations: relationsToBeFetched});
    }
    return this.fetch(options);
  },

  /**
   * Save Model & its relations
   * Note: Collection relations are not saved
   */
  saveAll: function(options) {
    options = options || {};
    var fns = [
      _.bind(this.save, this, null, options)
    ];
    _.each(this.relationDefinitions, function(relationAttributes, relationKey) {
      var relation = this.get(relationKey);
      if (relation && _.isFunction(relation.save)) {
        fns.push(_.bind(relation.save, relation, null, _.clone(options)));
      }
    }, this);
    return sequence(fns);
  },

  // apply function to this model & its relations
  applyToAll: function(fnStr, options) {
    options = options || {};
    var fns = [
      this[fnStr].apply(this, [options])
    ];
    _.each(this.relationDefinitions, function(relationAttributes, relationKey) {
      var relation = this.get(relationKey);
      if (relation) {
        fns.push(relation[fnStr](options));
      }
    }, this);
    return Promises.when.all(fns);
  },

  preSave: function() {
    return when.resolve();
  },

  afterSave: function() {
    return when.resolve();
  },

  preFetch: function() {
    return when.resolve();
  },

  afterFetch: function() {
    return when.resolve();
  },

  fetchAllRequired: function() {
    return this.relationDefinitions
      && Object.keys(this.relationDefinitions).length
      && this.fetchStatus !== 'all_fetched';
  },

  preDelete: function(options) {
    options = options || {};
    if (this.fetchAllRequired()) {
      options.ignoreFailures = true;
      // no need load collection models
      options.skipModelsFetch = true;
      return this.fetchAll(options);
    }
    return when.resolve();
  },

  afterDelete: function(options) {
    return when.resolve();
  },

  // omits relations from changedAttributes
  changedAttributesWithoutRelations: function() {
    var attrs = this.changedAttributes();
    var relationKeys = this.relationDefinitions ? Object.keys(this.relationDefinitions) : [];
    attrs = _.omit(attrs, relationKeys);
    return attrs;
  },

  attributesChanged: function(model, options) {
    var attrs = this.changedAttributesWithoutRelations();
    this._changedSinceSync = _.extend({}, this._changedSinceSync, attrs);
  },

  modelSynced: function(model, resp, options) {
    if (!this._attributesOnSync) {
      this._attributesOnSync = _.clone(this.attributes);
    }
  },

  changedSinceSync: function() {
    return this._changedSinceSync;
  },

  parse: function(resp, options) {
    this._changedSinceSync = {};
    this._attributesOnSync = false;
    return BaseModel.__super__.parse.apply(this, arguments);
  },

  // in context of serverbone Model.previousAttributes returns attributes that were set when last synced
  previousAttributes: function() {
    if (this._attributesOnSync) return _.clone(this._attributesOnSync);
    return _.clone(this._previousAttributes);
  }

});

BaseModel.Associations = Backbone.Associations;

// override db config during runtime
BaseModel.setDbDriver = function(dbSettings) {
  this.prototype.db = dbSettings.db;
  this.prototype.sync = dbSettings.sync;
  this.prototype.indexDb = dbSettings.indexDb;
};

// Instance methods

// Helpers

module.exports = BaseModel;
module.exports.formatProperties = formatProperties;<commit_msg>Fixes to fetchRequired<commit_after>var _ = require('lodash');
var parallel = require('when/parallel');
var sequence = require('when/sequence');
var Promises = require('backbone-promises');
var when = Promises.when;
var PromisedModel = Promises.Model;
var Backbone = require('backbone');
var SchemaModel = require('backbone-blueprint').ValidatingModel;
var ValidationError = require('../errors').ValidationError;
var logId = 'serverbone:models:base';
var _debug = require('debug');
var when = Promises.when;

var debug = {
  trace: _debug(logId + ':trace'),
  log: _debug(logId + ':log'),
  warn: _debug(logId + ':warn'),
  error: _debug(logId + ':error')
};

/**
 * Format 'templated' properties of object like {type: '{type}'}
 * using given this-context for the actual value
 * @param  {Object} properties
 * @return {Object}
 */
var formatProperties = function(properties) {
  var self = this;
  var realProperties = {};

  function getTemplateValue(property) {
    function getThisValue(match) {
      var cleanedValue = match.substring(1, match.length - 1);
      return self[cleanedValue];
    }
    return property.replace(/{([^}]+)}+/g, getThisValue);
  }

  for (var propertyKey in properties) {
    realProperties[propertyKey] = getTemplateValue(properties[propertyKey]);
  }

  return realProperties;
};

// convert error & reject
var failWithError = function(options, err) {
  options = options || {};
  if (options.ignoreFailures) return Promises.when.resolve();
  return when.reject(err);
};

var BaseModel = SchemaModel.extend({
  initialize: function(attributes, options) {
    //debug.trace('BaseModel.initialize');
    BaseModel.__super__.initialize.apply(this, [attributes, options]);
    this.options = options ? _.clone(options) : {};
    this._processSchema();
    // attributes which have changed since this model was synced
    this._changedSinceSync = {};
    // attributes which this model had when last synced
    this._attributesOnSync = false;
    this.on('change', this.attributesChanged, this);
    this.on('sync', this.modelSynced, this);
  },

  _processSchema: function() {
    if (!this.schema) return;
    this.indexes = this.schema.indexes;
  },

  url: function() {
    var key = this.dbBaseKey || this.type;
    if (this.isNew()) {
      return key;
    } else {
      return key + ':' + this.get(this.idAttribute);
    }
  },

  sync: function() {
    throw new Error('sync method should be overridden!');
  },

  save: function(key, val, options) {
    var opts = options || {};
    var self = this;
    if (key == null || typeof key === 'object') {
      opts = val || {};
    }
    var error = opts.error;
    var fns = [
      _.bind(self.preSave, self, opts),
      _.bind(PromisedModel.prototype.save, self, key, opts),
      _.bind(self.afterSave, self, opts)
    ];
    return sequence(fns).then(function(results) {
      return results[1];
    }, function(err) {
      if (error) error.call(opts, self, err);
      return failWithError(opts, err);
    });
  },

  fetch: function(options) {
    var self = this;

    options = options || {};

    var error = options.error;

    var fns = [
      _.bind(self.preFetch, self, options),
      _.bind(PromisedModel.prototype.fetch, self, options),
      _.bind(self.afterFetch, self, options)
    ];
    return sequence(fns).then(function () {
      self.fetchStatus = 'fetched';
      return self;
    }, function (err) {
      if (error) error.call(options, self, err);
      return failWithError(options, err);
    });
  },

  destroy: function(options) {
    options =  options || {};
    var fns = [
      _.bind(this.preDelete, this, _.clone(options)),
      _.bind(PromisedModel.prototype.destroy, this, options),
      _.bind(this.afterDelete, this, options)
    ];
    return sequence(fns)
      .then(function(results) {
        return results[1];
      }, _.bind(failWithError, null, options));
  },

  // stub, everyone can access
  canAccess: function() {
    return true;
  },

  //TODO: this is just a dummy method, should be implemented
  getRoles: function() {
    var roles = [];
    return roles;
  },

  // Field level access: get properties which user has permissions
  // field can override object level access mask
  propertiesWithAccess: function() {
    return Object.keys(this.schema.properties);
  },

  toJSON: function(options) {
    options = options || {};
    var json = BaseModel.__super__.toJSON.apply(this, arguments);
    return json;
  },

  validate: function(attrs, options) {
    options = options || {};
    var validationErrors = BaseModel.__super__.validate.apply(this, arguments);
    if (validationErrors) return new ValidationError({
      errors: validationErrors
    });
  },

  /**
   * Fetch current model & its relations
   * Need to fetch current model first in order to apply correct ids to relations
   */
  fetchAll: function(options) {
    debug.trace('fetchAll %s',JSON.stringify(options));
    options = options || {};
    options.action = options.action || 'read';
    var self = this;
    var when = Promises.when;
    options.action = 'read';
    function handleError(err) {
      if (options.ignoreFailures) {
        return when.resolve(self);
      } else {
        return when.reject(err);
      }
    }
    return this
      .fetch(options)
      .then(function() {
        if (!self.relationDefinitions) {
          return self;
        }
        return self
          .fetchRelations(options)
          .then(function() {
            return self;
          }, handleError);
      }, handleError);
  },

  /**
   * Fetches relations available based on current attributes
   * if options.onlyRelations Array is specified only those relations are fetched
   * e.g. fetchRelations({onlyRelations: ['user']}) will fetch only relation 'user'
   */
  fetchRelations: function(options) {
    options = options || {};
    var when = Promises.when;
    var self = this;
    var fns = [];
    _.each(self.relationDefinitions, function(relationAttributes, relationKey) {
      if (_.isArray(options.onlyRelations)) {
        if (options.onlyRelations.indexOf(relationKey) === -1) return;
      }
      var relation = self.get(relationKey);
      if (relation && !relation.url) {
        return;
      }
      if (relation && relation.fetch) {
        // When the run is parallel, clone the options so no shared promises happen.
        fns.push(_.bind(relation.fetch, relation, _.clone(options)));
      }
    }, this);

    return parallel(fns)
      .then(function relationsFetched() {
        self.fetchStatus = 'all_fetched';
        return self;
      }, function error(err) {
        if (options.ignoreFailures) {
          self.fetchStatus = 'all_fetched';
          return when.resolve(self);
        }
        return when.reject(err);
      });
  },

  /**
   * Fetch model/relations based on given projection.
   * Tries to avoid unnecessary fetches.
   * TODO: this does not support all projection options yet.
   * @param  {object} projection
   * @param  {object} options
   * @return {Promise}
   */
  fetchRequired: function(projection, options) {
    var requiredProperties = projection.onlyFields;
    var fetchRequired = _.any(requiredProperties, function(prop) {
      return this.get(prop) === undefined;
    }, this);
    var relationsToBeFetched = [];
    var relations = _.omit(
      projection,
      'onlyFields',
      'removeFields',
      'actor',
      'requiredDependencies'
    );
    _.each(relations, function(attrs, relKey) {
      var r = this.get(relKey);
      var missingKeys = _.any(attrs, function(attr) {
        return r && r.get && r.get(attr) === undefined;
      });
      if (!r || missingKeys) relationsToBeFetched.push(relKey);
    }, this);

    if (relationsToBeFetched.length) fetchRequired = true;

    if (!fetchRequired) {
      return when.resolve();
    }
    if (relationsToBeFetched.length) {
      var fetchOpts = _.extend({}, options, {
        onlyRelations: relationsToBeFetched
      });
      return this.fetchAll(fetchOpts);
    }
    return this.fetch(options);
  },

  /**
   * Save Model & its relations
   * Note: Collection relations are not saved
   */
  saveAll: function(options) {
    options = options || {};
    var fns = [
      _.bind(this.save, this, null, options)
    ];
    _.each(this.relationDefinitions, function(relationAttributes, relationKey) {
      var relation = this.get(relationKey);
      if (relation && _.isFunction(relation.save)) {
        fns.push(_.bind(relation.save, relation, null, _.clone(options)));
      }
    }, this);
    return sequence(fns);
  },

  // apply function to this model & its relations
  applyToAll: function(fnStr, options) {
    options = options || {};
    var fns = [
      this[fnStr].apply(this, [options])
    ];
    _.each(this.relationDefinitions, function(relationAttributes, relationKey) {
      var relation = this.get(relationKey);
      if (relation) {
        fns.push(relation[fnStr](options));
      }
    }, this);
    return Promises.when.all(fns);
  },

  preSave: function() {
    return when.resolve();
  },

  afterSave: function() {
    return when.resolve();
  },

  preFetch: function() {
    return when.resolve();
  },

  afterFetch: function() {
    return when.resolve();
  },

  fetchAllRequired: function() {
    return this.relationDefinitions
      && Object.keys(this.relationDefinitions).length
      && this.fetchStatus !== 'all_fetched';
  },

  preDelete: function(options) {
    options = options || {};
    if (this.fetchAllRequired()) {
      options.ignoreFailures = true;
      // no need load collection models
      options.skipModelsFetch = true;
      return this.fetchAll(options);
    }
    return when.resolve();
  },

  afterDelete: function(options) {
    return when.resolve();
  },

  // omits relations from changedAttributes
  changedAttributesWithoutRelations: function() {
    var attrs = this.changedAttributes();
    var relationKeys = this.relationDefinitions ? Object.keys(this.relationDefinitions) : [];
    attrs = _.omit(attrs, relationKeys);
    return attrs;
  },

  attributesChanged: function(model, options) {
    var attrs = this.changedAttributesWithoutRelations();
    this._changedSinceSync = _.extend({}, this._changedSinceSync, attrs);
  },

  modelSynced: function(model, resp, options) {
    if (!this._attributesOnSync) {
      this._attributesOnSync = _.clone(this.attributes);
    }
  },

  changedSinceSync: function() {
    return this._changedSinceSync;
  },

  parse: function(resp, options) {
    this._changedSinceSync = {};
    this._attributesOnSync = false;
    return BaseModel.__super__.parse.apply(this, arguments);
  },

  // in context of serverbone Model.previousAttributes returns attributes that were set when last synced
  previousAttributes: function() {
    if (this._attributesOnSync) return _.clone(this._attributesOnSync);
    return _.clone(this._previousAttributes);
  }

});

BaseModel.Associations = Backbone.Associations;

// override db config during runtime
BaseModel.setDbDriver = function(dbSettings) {
  this.prototype.db = dbSettings.db;
  this.prototype.sync = dbSettings.sync;
  this.prototype.indexDb = dbSettings.indexDb;
};

// Instance methods

// Helpers

module.exports = BaseModel;
module.exports.formatProperties = formatProperties;<|endoftext|>


<commit_before>import path from 'path';

import {Emitter} from 'event-kit';
import fs from 'fs-extra';

import {getNullActionPipelineManager} from '../action-pipeline';
import CompositeGitStrategy from '../composite-git-strategy';
import Author, {nullAuthor} from './author';
import Branch from './branch';
import {Loading, Absent, LoadingGuess, AbsentGuess} from './repository-states';

const MERGE_MARKER_REGEX = /^(>|<){7} \S+$/m;

// Internal option keys used to designate the desired initial state of a Repository.
const initialStateSym = Symbol('initialState');

export default class Repository {
  constructor(workingDirectoryPath, gitStrategy = null, options = {}) {
    this.workingDirectoryPath = workingDirectoryPath;
    this.git = gitStrategy || CompositeGitStrategy.create(workingDirectoryPath);

    this.emitter = new Emitter();

    this.loadPromise = new Promise(resolve => {
      const sub = this.onDidChangeState(() => {
        if (!this.isLoading()) {
          resolve();
          sub.dispose();
        } else if (this.isDestroyed()) {
          sub.dispose();
        }
      });
    });

    this.pipelineManager = options.pipelineManager || getNullActionPipelineManager();
    this.transitionTo(options[initialStateSym] || Loading);
  }

  static absent(options) {
    return new Repository(null, null, {[initialStateSym]: Absent, ...options});
  }

  static loadingGuess(options) {
    return new Repository(null, null, {[initialStateSym]: LoadingGuess, ...options});
  }

  static absentGuess(options) {
    return new Repository(null, null, {[initialStateSym]: AbsentGuess, ...options});
  }

  // State management //////////////////////////////////////////////////////////////////////////////////////////////////

  transition(currentState, StateConstructor, ...payload) {
    if (currentState !== this.state) {
      // Attempted transition from a non-active state, most likely from an asynchronous start() method.
      return Promise.resolve();
    }

    const nextState = new StateConstructor(this, ...payload);
    this.state = nextState;

    this.emitter.emit('did-change-state', {from: currentState, to: this.state});
    if (!this.isDestroyed()) {
      this.emitter.emit('did-update');
    }

    return this.state.start();
  }

  transitionTo(StateConstructor, ...payload) {
    return this.transition(this.state, StateConstructor, ...payload);
  }

  getLoadPromise() {
    return this.isAbsent() ? Promise.reject(new Error('An absent repository will never load')) : this.loadPromise;
  }

  /*
   * Use `callback` to request user input from all git strategies.
   */
  setPromptCallback(callback) {
    this.git.getImplementers().forEach(strategy => strategy.setPromptCallback(callback));
  }

  // Pipeline
  getPipeline(actionName) {
    const actionKey = this.pipelineManager.actionKeys[actionName];
    return this.pipelineManager.getPipeline(actionKey);
  }

  executePipelineAction(actionName, fn, ...args) {
    const pipeline = this.getPipeline(actionName);
    return pipeline.run(fn, this, ...args);
  }

  // Event subscription ////////////////////////////////////////////////////////////////////////////////////////////////

  onDidDestroy(callback) {
    return this.emitter.on('did-destroy', callback);
  }

  onDidChangeState(callback) {
    return this.emitter.on('did-change-state', callback);
  }

  onDidUpdate(callback) {
    return this.emitter.on('did-update', callback);
  }

  onPullError(callback) {
    return this.emitter.on('pull-error', callback);
  }

  didPullError() {
    return this.emitter.emit('pull-error');
  }

  // State-independent actions /////////////////////////////////////////////////////////////////////////////////////////
  // Actions that use direct filesystem access or otherwise don't need `this.git` to be available.

  async pathHasMergeMarkers(relativePath) {
    try {
      const contents = await fs.readFile(path.join(this.getWorkingDirectoryPath(), relativePath), {encoding: 'utf8'});
      return MERGE_MARKER_REGEX.test(contents);
    } catch (e) {
      // EISDIR implies this is a submodule
      if (e.code === 'ENOENT' || e.code === 'EISDIR') { return false; } else { throw e; }
    }
  }

  async getMergeMessage() {
    try {
      const contents = await fs.readFile(path.join(this.getGitDirectoryPath(), 'MERGE_MSG'), {encoding: 'utf8'});
      return contents.split(/\n/).filter(line => line.length > 0 && !line.startsWith('#')).join('\n');
    } catch (e) {
      return null;
    }
  }

  // State-independent accessors ///////////////////////////////////////////////////////////////////////////////////////

  getWorkingDirectoryPath() {
    return this.workingDirectoryPath;
  }

  setGitDirectoryPath(gitDirectoryPath) {
    this._gitDirectoryPath = gitDirectoryPath;
  }

  getGitDirectoryPath() {
    if (this._gitDirectoryPath) {
      return this._gitDirectoryPath;
    } else if (this.getWorkingDirectoryPath()) {
      return path.join(this.getWorkingDirectoryPath(), '.git');
    } else {
      // Absent/Loading/etc.
      return null;
    }
  }

  isInState(stateName) {
    return this.state.constructor.name === stateName;
  }

  toString() {
    return `Repository(state=${this.state.constructor.name}, workdir="${this.getWorkingDirectoryPath()}")`;
  }

  // Compound Getters //////////////////////////////////////////////////////////////////////////////////////////////////
  // Accessor methods for data derived from other, state-provided getters.

  async getCurrentBranch() {
    const branches = await this.getBranches();
    const head = branches.getHeadBranch();
    if (head.isPresent()) {
      return head;
    }

    const description = await this.getHeadDescription();
    return Branch.createDetached(description || 'no branch');
  }

  async getUnstagedChanges() {
    const {unstagedFiles} = await this.getStatusBundle();
    return Object.keys(unstagedFiles)
      .sort()
      .map(filePath => { return {filePath, status: unstagedFiles[filePath]}; });
  }

  async getStagedChanges() {
    const {stagedFiles} = await this.getStatusBundle();
    return Object.keys(stagedFiles)
      .sort()
      .map(filePath => { return {filePath, status: stagedFiles[filePath]}; });
  }

  async getMergeConflicts() {
    const {mergeConflictFiles} = await this.getStatusBundle();
    return Object.keys(mergeConflictFiles).map(filePath => {
      return {filePath, status: mergeConflictFiles[filePath]};
    });
  }

  async isPartiallyStaged(fileName) {
    const {unstagedFiles, stagedFiles} = await this.getStatusBundle();
    const u = unstagedFiles[fileName];
    const s = stagedFiles[fileName];
    return (u === 'modified' && s === 'modified') ||
      (u === 'modified' && s === 'added') ||
      (u === 'added' && s === 'deleted') ||
      (u === 'deleted' && s === 'modified');
  }

  async getRemoteForBranch(branchName) {
    const name = await this.getConfig(`branch.${branchName}.remote`);
    return (await this.getRemotes()).withName(name);
  }

  async saveDiscardHistory() {
    if (this.isDestroyed()) {
      return;
    }

    const historySha = await this.createDiscardHistoryBlob();
    if (this.isDestroyed()) {
      return;
    }
    await this.setConfig('atomGithub.historySha', historySha);
  }

  async getCommitter(options = {}) {
    const output = await this.getConfig(['--get-regexp', '^user.*'], options);
    const committer = {name: null, email: null};
    // todo (tt, 4/2018): do we need null byte terminated output here for Windows?
    if (output) {
      output.trim().split('\n').forEach(line => {
        if (line.includes('user.email')) {
          committer.email = line.slice(11);
        } else if (line.includes('user.name')) {
          committer.name = line.slice(10);
        }
      });
    }

    return committer.name !== null && committer.email !== null
      ? new Author(committer.email, committer.name)
      : nullAuthor;
  }

  // todo (@annthurium, 3/2019): refactor GitHubTabController etc to use this method.
  async getCurrentGitHubRemote() {
    let currentRemote = null;

    const remotes = await this.getRemotes();

    const gitHubRemotes = remotes.filter(remote => remote.isGithubRepo());
    const selectedRemoteName = await this.getConfig('atomGithub.currentRemote');
    currentRemote = gitHubRemotes.withName(selectedRemoteName);

    if (!currentRemote.isPresent() && gitHubRemotes.size() === 1) {
      currentRemote = Array.from(gitHubRemotes)[0];
    }
    // todo: handle the case where multiple remotes are available and no chosen remote is set.
    return currentRemote;
  }

  async hasGitHubRemote(host, owner, name) {
    const remotes = await this.getRemotes();
    return remotes.matchingGitHubRepository(owner, name).length > 0;
  }
}

// The methods named here will be delegated to the current State.
//
// Duplicated here rather than just using `expectedDelegates` directly so that this file is grep-friendly for answering
// the question of "what all can a Repository do exactly".
const delegates = [
  'isLoadingGuess',
  'isAbsentGuess',
  'isAbsent',
  'isLoading',
  'isEmpty',
  'isPresent',
  'isTooLarge',
  'isDestroyed',

  'isUndetermined',
  'showGitTabInit',
  'showGitTabInitInProgress',
  'showGitTabLoading',
  'showStatusBarTiles',
  'hasDirectory',
  'isPublishable',

  'init',
  'clone',
  'destroy',
  'refresh',
  'observeFilesystemChange',
  'updateCommitMessageAfterFileSystemChange',

  'stageFiles',
  'unstageFiles',
  'stageFilesFromParentCommit',
  'stageFileModeChange',
  'stageFileSymlinkChange',
  'applyPatchToIndex',
  'applyPatchToWorkdir',

  'commit',

  'merge',
  'abortMerge',
  'checkoutSide',
  'mergeFile',
  'writeMergeConflictToIndex',

  'checkout',
  'checkoutPathsAtRevision',

  'undoLastCommit',

  'fetch',
  'pull',
  'push',

  'setConfig',

  'createBlob',
  'expandBlobToFile',

  'createDiscardHistoryBlob',
  'updateDiscardHistory',
  'storeBeforeAndAfterBlobs',
  'restoreLastDiscardInTempFiles',
  'popDiscardHistory',
  'clearDiscardHistory',
  'discardWorkDirChangesForPaths',

  'getStatusBundle',
  'getStatusesForChangedFiles',
  'getFilePatchForPath',
  'getDiffsForFilePath',
  'getStagedChangesPatch',
  'readFileFromIndex',

  'getLastCommit',
  'getCommit',
  'getRecentCommits',
  'isCommitPushed',

  'getAuthors',

  'getBranches',
  'getHeadDescription',

  'isMerging',
  'isRebasing',

  'getRemotes',
  'addRemote',

  'getAheadCount',
  'getBehindCount',

  'getConfig',
  'unsetConfig',

  'getBlobContents',

  'hasDiscardHistory',
  'getDiscardHistory',
  'getLastHistorySnapshots',

  'getOperationStates',

  'setCommitMessage',
  'getCommitMessage',
  'fetchCommitMessageTemplate',
  'getCache',
];

for (let i = 0; i < delegates.length; i++) {
  const delegate = delegates[i];

  Repository.prototype[delegate] = function(...args) {
    return this.state[delegate](...args);
  };
}
<commit_msg>Use getConfig directly in getCommitter for improved cache interaction<commit_after>import path from 'path';

import {Emitter} from 'event-kit';
import fs from 'fs-extra';
import yubikiri from 'yubikiri';

import {getNullActionPipelineManager} from '../action-pipeline';
import CompositeGitStrategy from '../composite-git-strategy';
import Author, {nullAuthor} from './author';
import Branch from './branch';
import {Loading, Absent, LoadingGuess, AbsentGuess} from './repository-states';

const MERGE_MARKER_REGEX = /^(>|<){7} \S+$/m;

// Internal option keys used to designate the desired initial state of a Repository.
const initialStateSym = Symbol('initialState');

export default class Repository {
  constructor(workingDirectoryPath, gitStrategy = null, options = {}) {
    this.workingDirectoryPath = workingDirectoryPath;
    this.git = gitStrategy || CompositeGitStrategy.create(workingDirectoryPath);

    this.emitter = new Emitter();

    this.loadPromise = new Promise(resolve => {
      const sub = this.onDidChangeState(() => {
        if (!this.isLoading()) {
          resolve();
          sub.dispose();
        } else if (this.isDestroyed()) {
          sub.dispose();
        }
      });
    });

    this.pipelineManager = options.pipelineManager || getNullActionPipelineManager();
    this.transitionTo(options[initialStateSym] || Loading);
  }

  static absent(options) {
    return new Repository(null, null, {[initialStateSym]: Absent, ...options});
  }

  static loadingGuess(options) {
    return new Repository(null, null, {[initialStateSym]: LoadingGuess, ...options});
  }

  static absentGuess(options) {
    return new Repository(null, null, {[initialStateSym]: AbsentGuess, ...options});
  }

  // State management //////////////////////////////////////////////////////////////////////////////////////////////////

  transition(currentState, StateConstructor, ...payload) {
    if (currentState !== this.state) {
      // Attempted transition from a non-active state, most likely from an asynchronous start() method.
      return Promise.resolve();
    }

    const nextState = new StateConstructor(this, ...payload);
    this.state = nextState;

    this.emitter.emit('did-change-state', {from: currentState, to: this.state});
    if (!this.isDestroyed()) {
      this.emitter.emit('did-update');
    }

    return this.state.start();
  }

  transitionTo(StateConstructor, ...payload) {
    return this.transition(this.state, StateConstructor, ...payload);
  }

  getLoadPromise() {
    return this.isAbsent() ? Promise.reject(new Error('An absent repository will never load')) : this.loadPromise;
  }

  /*
   * Use `callback` to request user input from all git strategies.
   */
  setPromptCallback(callback) {
    this.git.getImplementers().forEach(strategy => strategy.setPromptCallback(callback));
  }

  // Pipeline
  getPipeline(actionName) {
    const actionKey = this.pipelineManager.actionKeys[actionName];
    return this.pipelineManager.getPipeline(actionKey);
  }

  executePipelineAction(actionName, fn, ...args) {
    const pipeline = this.getPipeline(actionName);
    return pipeline.run(fn, this, ...args);
  }

  // Event subscription ////////////////////////////////////////////////////////////////////////////////////////////////

  onDidDestroy(callback) {
    return this.emitter.on('did-destroy', callback);
  }

  onDidChangeState(callback) {
    return this.emitter.on('did-change-state', callback);
  }

  onDidUpdate(callback) {
    return this.emitter.on('did-update', callback);
  }

  onPullError(callback) {
    return this.emitter.on('pull-error', callback);
  }

  didPullError() {
    return this.emitter.emit('pull-error');
  }

  // State-independent actions /////////////////////////////////////////////////////////////////////////////////////////
  // Actions that use direct filesystem access or otherwise don't need `this.git` to be available.

  async pathHasMergeMarkers(relativePath) {
    try {
      const contents = await fs.readFile(path.join(this.getWorkingDirectoryPath(), relativePath), {encoding: 'utf8'});
      return MERGE_MARKER_REGEX.test(contents);
    } catch (e) {
      // EISDIR implies this is a submodule
      if (e.code === 'ENOENT' || e.code === 'EISDIR') { return false; } else { throw e; }
    }
  }

  async getMergeMessage() {
    try {
      const contents = await fs.readFile(path.join(this.getGitDirectoryPath(), 'MERGE_MSG'), {encoding: 'utf8'});
      return contents.split(/\n/).filter(line => line.length > 0 && !line.startsWith('#')).join('\n');
    } catch (e) {
      return null;
    }
  }

  // State-independent accessors ///////////////////////////////////////////////////////////////////////////////////////

  getWorkingDirectoryPath() {
    return this.workingDirectoryPath;
  }

  setGitDirectoryPath(gitDirectoryPath) {
    this._gitDirectoryPath = gitDirectoryPath;
  }

  getGitDirectoryPath() {
    if (this._gitDirectoryPath) {
      return this._gitDirectoryPath;
    } else if (this.getWorkingDirectoryPath()) {
      return path.join(this.getWorkingDirectoryPath(), '.git');
    } else {
      // Absent/Loading/etc.
      return null;
    }
  }

  isInState(stateName) {
    return this.state.constructor.name === stateName;
  }

  toString() {
    return `Repository(state=${this.state.constructor.name}, workdir="${this.getWorkingDirectoryPath()}")`;
  }

  // Compound Getters //////////////////////////////////////////////////////////////////////////////////////////////////
  // Accessor methods for data derived from other, state-provided getters.

  async getCurrentBranch() {
    const branches = await this.getBranches();
    const head = branches.getHeadBranch();
    if (head.isPresent()) {
      return head;
    }

    const description = await this.getHeadDescription();
    return Branch.createDetached(description || 'no branch');
  }

  async getUnstagedChanges() {
    const {unstagedFiles} = await this.getStatusBundle();
    return Object.keys(unstagedFiles)
      .sort()
      .map(filePath => { return {filePath, status: unstagedFiles[filePath]}; });
  }

  async getStagedChanges() {
    const {stagedFiles} = await this.getStatusBundle();
    return Object.keys(stagedFiles)
      .sort()
      .map(filePath => { return {filePath, status: stagedFiles[filePath]}; });
  }

  async getMergeConflicts() {
    const {mergeConflictFiles} = await this.getStatusBundle();
    return Object.keys(mergeConflictFiles).map(filePath => {
      return {filePath, status: mergeConflictFiles[filePath]};
    });
  }

  async isPartiallyStaged(fileName) {
    const {unstagedFiles, stagedFiles} = await this.getStatusBundle();
    const u = unstagedFiles[fileName];
    const s = stagedFiles[fileName];
    return (u === 'modified' && s === 'modified') ||
      (u === 'modified' && s === 'added') ||
      (u === 'added' && s === 'deleted') ||
      (u === 'deleted' && s === 'modified');
  }

  async getRemoteForBranch(branchName) {
    const name = await this.getConfig(`branch.${branchName}.remote`);
    return (await this.getRemotes()).withName(name);
  }

  async saveDiscardHistory() {
    if (this.isDestroyed()) {
      return;
    }

    const historySha = await this.createDiscardHistoryBlob();
    if (this.isDestroyed()) {
      return;
    }
    await this.setConfig('atomGithub.historySha', historySha);
  }

  async getCommitter(options = {}) {
    const committer = await yubikiri({
      email: this.getConfig('user.email', options),
      name: this.getConfig('user.name', options),
    });

    return committer.name !== null && committer.email !== null
      ? new Author(committer.email, committer.name)
      : nullAuthor;
  }

  // todo (@annthurium, 3/2019): refactor GitHubTabController etc to use this method.
  async getCurrentGitHubRemote() {
    let currentRemote = null;

    const remotes = await this.getRemotes();

    const gitHubRemotes = remotes.filter(remote => remote.isGithubRepo());
    const selectedRemoteName = await this.getConfig('atomGithub.currentRemote');
    currentRemote = gitHubRemotes.withName(selectedRemoteName);

    if (!currentRemote.isPresent() && gitHubRemotes.size() === 1) {
      currentRemote = Array.from(gitHubRemotes)[0];
    }
    // todo: handle the case where multiple remotes are available and no chosen remote is set.
    return currentRemote;
  }

  async hasGitHubRemote(host, owner, name) {
    const remotes = await this.getRemotes();
    return remotes.matchingGitHubRepository(owner, name).length > 0;
  }
}

// The methods named here will be delegated to the current State.
//
// Duplicated here rather than just using `expectedDelegates` directly so that this file is grep-friendly for answering
// the question of "what all can a Repository do exactly".
const delegates = [
  'isLoadingGuess',
  'isAbsentGuess',
  'isAbsent',
  'isLoading',
  'isEmpty',
  'isPresent',
  'isTooLarge',
  'isDestroyed',

  'isUndetermined',
  'showGitTabInit',
  'showGitTabInitInProgress',
  'showGitTabLoading',
  'showStatusBarTiles',
  'hasDirectory',
  'isPublishable',

  'init',
  'clone',
  'destroy',
  'refresh',
  'observeFilesystemChange',
  'updateCommitMessageAfterFileSystemChange',

  'stageFiles',
  'unstageFiles',
  'stageFilesFromParentCommit',
  'stageFileModeChange',
  'stageFileSymlinkChange',
  'applyPatchToIndex',
  'applyPatchToWorkdir',

  'commit',

  'merge',
  'abortMerge',
  'checkoutSide',
  'mergeFile',
  'writeMergeConflictToIndex',

  'checkout',
  'checkoutPathsAtRevision',

  'undoLastCommit',

  'fetch',
  'pull',
  'push',

  'setConfig',

  'createBlob',
  'expandBlobToFile',

  'createDiscardHistoryBlob',
  'updateDiscardHistory',
  'storeBeforeAndAfterBlobs',
  'restoreLastDiscardInTempFiles',
  'popDiscardHistory',
  'clearDiscardHistory',
  'discardWorkDirChangesForPaths',

  'getStatusBundle',
  'getStatusesForChangedFiles',
  'getFilePatchForPath',
  'getDiffsForFilePath',
  'getStagedChangesPatch',
  'readFileFromIndex',

  'getLastCommit',
  'getCommit',
  'getRecentCommits',
  'isCommitPushed',

  'getAuthors',

  'getBranches',
  'getHeadDescription',

  'isMerging',
  'isRebasing',

  'getRemotes',
  'addRemote',

  'getAheadCount',
  'getBehindCount',

  'getConfig',
  'unsetConfig',

  'getBlobContents',

  'hasDiscardHistory',
  'getDiscardHistory',
  'getLastHistorySnapshots',

  'getOperationStates',

  'setCommitMessage',
  'getCommitMessage',
  'fetchCommitMessageTemplate',
  'getCache',
];

for (let i = 0; i < delegates.length; i++) {
  const delegate = delegates[i];

  Repository.prototype[delegate] = function(...args) {
    return this.state[delegate](...args);
  };
}
<|endoftext|>


<commit_before>  'use strict';

const am = require('./am.js');
  var sleeboard = function () {
    if (!(this instanceof sleeboard)) {
      return new sleeboard()
    }

      getInputJson();

    var lang,
      scope,
      maxInserted = 0,
      ignoreKeyCodes = [8, 10, 18, 35, 36, 37, 38, 39, 40, 127];

    var finalText = '';
    /**
     * Write the Symbol to the right position on input
     * FIXME: caret gets hidden when overflow
     * @param vm
     * @param entry
     */
    function writeOnField(entry) {
      if (entry) {
        maxInserted = scope['_scope'] ? 0 : maxInserted;
        var sub = finalText.substring(0, finalText.length - (maxInserted));
        if (scope['_scope']) {
          maxInserted = 1;
        } else {
          maxInserted = maxInserted < entry.length ? entry.length : maxInserted;
        }
        return  sub + entry;
      }
      return '';
    }

    /**
     * Shrink Scope for Performance
     * @param char
     */
    function shrinkScope(char) {
      if (scope[char]) {
        scope = scope[char]['next'] ? scope[char]['next'] : lang;
      } else {
        scope = lang;
      }
    }

    /**
     * Get Symbol from Character
     * @param char
     * @returns {*}
     */
    function getSymbolFromScope(char) {
      scope = scope ? scope : lang;
      if (scope[char]) {
        return scope[char]['value'];
      } else if (lang[char]) {
        scope = lang;
        return scope[char]['value'];
      } else {
        scope = lang;
        return char;
      }
    }

    /**
     * handler
     * @param text
     */
    function handler(text) {
      var splitString = text.split('');
      splitString.forEach(char => {

        if (char) {
          var symbol = getSymbolFromScope(char);
          finalText = writeOnField(symbol);
          shrinkScope(char);
        }
      })
      var keyvalue = [];
      if(!scope['_scope']){
        var example = finalText.slice(0, -1);
        keyvalue = Object.keys(scope).map((key)=>{
         var chars = key;
         var scopeCopy = scope;
         var value = scopeCopy[key].value
         while(!scopeCopy[key].value){
          scopeCopy = scopeCopy[key].next
          key = Object.keys(scopeCopy)[0]
          chars = chars + key
          value = scopeCopy[key].value
         }
         var result = example+value
         return {chars, result}
        })
        keyvalue.unshift({chars: '', result: finalText})
      }else {
        keyvalue.unshift({chars: '', result: finalText})
      }
      return keyvalue;
    }

    /**
     * Request server for json
     */
    function getInputJson() {
      lang = am
      lang['_scope'] = 'all';
    }

    /**
     * Change Input Type
     * @param fileName
     */
     this.getAmharic = function(text){
        finalText = ""
	getInputJson()
	scope = lang
        return handler(text)
     }

  };

module.exports = sleeboard()
<commit_msg>refactoring<commit_after>  'use strict';

const am = require('./am.js');
  var sleeboard = function () {
    if (!(this instanceof sleeboard)) {
      return new sleeboard()
    }

      getInputJson();

    var lang,
      scope,
      maxInserted = 0,
      ignoreKeyCodes = [8, 10, 18, 35, 36, 37, 38, 39, 40, 127];

    var finalText = '';
    /**
     * Write the Symbol to the right position on input
     * FIXME: caret gets hidden when overflow
     * @param vm
     * @param entry
     */
    function writeOnField(entry) {
      if (entry) {
        maxInserted = scope['_scope'] ? 0 : maxInserted;
        var sub = finalText.substring(0, finalText.length - (maxInserted));
        if (scope['_scope']) {
          maxInserted = 1;
        } else {
          maxInserted = maxInserted < entry.length ? entry.length : maxInserted;
        }
        return  sub + entry;
      }
      return '';
    }

    /**
     * Shrink Scope for Performance
     * @param char
     */
    function shrinkScope(char) {
      if (scope[char]) {
        scope = scope[char]['next'] ? scope[char]['next'] : lang;
      } else {
        scope = lang;
      }
    }

    /**
     * Get Symbol from Character
     * @param char
     * @returns {*}
     */
    function getSymbolFromScope(char) {
      scope = scope ? scope : lang;
      if (scope[char]) {
        return scope[char]['value'];
      } else if (lang[char]) {
        scope = lang;
        return scope[char]['value'];
      } else {
        scope = lang;
        return char;
      }
    }

    /**
     * handler
     * @param text
     */
    function handler(text) {
      var splitString = text.split('');
      splitString.forEach(char => {

        if (char) {
          var symbol = getSymbolFromScope(char);
          finalText = writeOnField(symbol);
          shrinkScope(char);
        }
      })
      var keyvalue = [];
      if(!scope['_scope']){
        var example = finalText.slice(0, -1);
        keyvalue = Object.keys(scope).map((key)=>{
         var chars = key;
         var scopeCopy = scope;
         var value = scopeCopy[key].value
         while(!scopeCopy[key].value){
          scopeCopy = scopeCopy[key].next
          key = Object.keys(scopeCopy)[0]
          chars = chars + key
          value = scopeCopy[key].value
         }
         var result = example+value
         return {chars, result}
        })
        keyvalue.unshift({chars: '', result: finalText})
      }else {
        keyvalue.unshift({chars: '', result: finalText})
      }
      return keyvalue;
    }

    /**
     * Request server for json
     */
    function getInputJson() {
      lang = am
      lang['_scope'] = 'all';
    }

    /**
     * Change Input Type
     * @param fileName
     */
     this.getAmharic = function(text){
        finalText = ""
        scope = lang
        return handler(text)
     }

  };

module.exports = sleeboard()
<|endoftext|>


<commit_before>import Map from 'shared/model/map';
import { sortBy, last, get } from 'lodash';
import { computed, action, observable, toJS } from 'mobx';
import Exercise from './exercises/exercise';

const NEW = 'new';

export class ExerciseVersions extends Map {

  get(version) {
    if (version === 'latest') {
      return last(sortBy(this.array, 'version'));
    } else {
      return super.get(version);
    }
  }

}

export class ExercisesMap extends Map {

  findOrCreateNewRecord() {
    let ex = this.get(NEW);
    if (!ex) {
      ex = Exercise.build({ id: NEW });
      this.set(NEW, ex);
    }
    return ex;
  }

  get(idWithVersion) {
    const [id, version = 'latest'] = String(idWithVersion).split('@');
    if (id === NEW) { return super.get(id); }
    const versions = super.get(id);
    return versions ? versions.get(version) : null;
  }

  fetch(id) {
    if (!String(id).match(/@/)){ id = `${id}@latest`; }
    return { id };
  }

  @action onLoaded({ data, exercise }) {
    let versions = super.get(data.number);
    if (!versions) {
      versions = new ExerciseVersions();
      this.set(data.number, versions);
    }
    let existing = versions.get(data.version);
    if (exercise) {
      versions.set(data.version, exercise);
      existing = exercise;
    }
    existing ? existing.update(data) : versions.set(data.version, exercise || new Exercise(data));
  }

  @action ensureLoaded(numberWithVersion) {
    if (numberWithVersion === NEW) {
      this.findOrCreateNewRecord();
    } else if (!this.get(numberWithVersion)) {
      this.fetch(numberWithVersion);
    }
  }

  publish(exercise) {
    return { uid: exercise.uid, data: exercise.serialize() };
  }

  saveDraft(exercise) {
    const req = { data: exercise.serialize() };
    if (exercise.isNew) {
      Object.assign(req, { url: 'exercises', method: 'POST' });
    }
    return req;
  }

  onSaved({ data }, [exercise]) {
    // if (exercise.isNew) {
    //   this.delete(NEW);
    // } else {
    //   this.delete(exercise.number);
    // }
    exercise.error = null;
    this.onLoaded({ data, exercise });
  }

  onError(error, [exercise]) {
    exercise.error = get(error, 'response.data.errors[0].message', error);
  }

}

const exercisesMap = new ExercisesMap();

export { Exercise };
export default exercisesMap;
<commit_msg>cleanup deleted code<commit_after>import Map from 'shared/model/map';
import { sortBy, last, get } from 'lodash';
import { computed, action, observable, toJS } from 'mobx';
import Exercise from './exercises/exercise';

const NEW = 'new';

export class ExerciseVersions extends Map {

  get(version) {
    if (version === 'latest') {
      return last(sortBy(this.array, 'version'));
    } else {
      return super.get(version);
    }
  }

}

export class ExercisesMap extends Map {

  findOrCreateNewRecord() {
    let ex = this.get(NEW);
    if (!ex) {
      ex = Exercise.build({ id: NEW });
      this.set(NEW, ex);
    }
    return ex;
  }

  get(idWithVersion) {
    const [id, version = 'latest'] = String(idWithVersion).split('@');
    if (id === NEW) { return super.get(id); }
    const versions = super.get(id);
    return versions ? versions.get(version) : null;
  }

  fetch(id) {
    if (!String(id).match(/@/)){ id = `${id}@latest`; }
    return { id };
  }

  @action onLoaded({ data, exercise }) {
    let versions = super.get(data.number);
    if (!versions) {
      versions = new ExerciseVersions();
      this.set(data.number, versions);
    }
    let existing = versions.get(data.version);
    if (exercise) {
      versions.set(data.version, exercise);
      existing = exercise;
    }
    existing ? existing.update(data) : versions.set(data.version, exercise || new Exercise(data));
  }

  @action ensureLoaded(numberWithVersion) {
    if (numberWithVersion === NEW) {
      this.findOrCreateNewRecord();
    } else if (!this.get(numberWithVersion)) {
      this.fetch(numberWithVersion);
    }
  }

  publish(exercise) {
    return { uid: exercise.uid, data: exercise.serialize() };
  }

  saveDraft(exercise) {
    const req = { data: exercise.serialize() };
    if (exercise.isNew) {
      Object.assign(req, { url: 'exercises', method: 'POST' });
    }
    return req;
  }

  onSaved({ data }, [exercise]) {
    exercise.error = null;
    this.onLoaded({ data, exercise });
  }

  onError(error, [exercise]) {
    exercise.error = get(error, 'response.data.errors[0].message', error);
  }

}

const exercisesMap = new ExercisesMap();

export { Exercise };
export default exercisesMap;
<|endoftext|>


<commit_before>export default class FilterModule {
    filter(msg) {
        return msg;
    }
}<commit_msg>FilterModule: Add JSDocs<commit_after>import Promise from "bluebird";

export default class FilterModule {
    /**
     * Gets passed a message, optionally executes actions upon it, and returns a message.
     * The filter chain can be broken by returning a rejected promise.
     *
     * @param {*} msg The received message object.
     * @return {object|Promise.<*>} The resulting message or a promise of it.
     */
    filter(msg) {
        return msg;
    }
}<|endoftext|>


<commit_before>var falcor = require('./falcor');

var Observable  = falcor.Observable,
    valuesMixin = { format: { value: "AsValues"  } },
    jsonMixin   = { format: { value: "AsPathMap" } },
    jsongMixin  = { format: { value: "AsJSONG"   } };

function ModelResponse(forEach) {
    this._subscribe = forEach;
}

ModelResponse.create = function(forEach) {
    return new ModelResponse(forEach);
};

function noop() {};
function mixin(self) {
    var mixins = Array.prototype.slice.call(arguments, 1);
    return new ModelResponse(function(other) {
        return self.subscribe(mixins.reduce(function(proto, mixin) {
            return Object.create(proto, mixin);
        }, other));
    });
};

ModelResponse.prototype = Observable.create(noop);
ModelResponse.prototype.format = "AsPathMap";
ModelResponse.prototype.toPathValues = function() {
    return mixin(this, valuesMixin);
};
ModelResponse.prototype.toJSON = function() {
    return mixin(this, jsonMixin);
};
ModelResponse.prototype.toJSONG = function() {
    return mixin(this, jsongMixin);
};

module.exports = ModelResponse;
<commit_msg>Fix ModelResponse falcor require case<commit_after>var falcor = require('./Falcor');

var Observable  = falcor.Observable,
    valuesMixin = { format: { value: "AsValues"  } },
    jsonMixin   = { format: { value: "AsPathMap" } },
    jsongMixin  = { format: { value: "AsJSONG"   } };

function ModelResponse(forEach) {
    this._subscribe = forEach;
}

ModelResponse.create = function(forEach) {
    return new ModelResponse(forEach);
};

function noop() {};
function mixin(self) {
    var mixins = Array.prototype.slice.call(arguments, 1);
    return new ModelResponse(function(other) {
        return self.subscribe(mixins.reduce(function(proto, mixin) {
            return Object.create(proto, mixin);
        }, other));
    });
};

ModelResponse.prototype = Observable.create(noop);
ModelResponse.prototype.format = "AsPathMap";
ModelResponse.prototype.toPathValues = function() {
    return mixin(this, valuesMixin);
};
ModelResponse.prototype.toJSON = function() {
    return mixin(this, jsonMixin);
};
ModelResponse.prototype.toJSONG = function() {
    return mixin(this, jsongMixin);
};

module.exports = ModelResponse;
<|endoftext|>


<commit_before>'use strict'

// TODO module descriptors
const suffixTest = /\.json$/;
const resolve = require('path').resolve;
const fs = require('fs');
const root = resolve(process.argv[2] || '/home/adioo/Repos') + '/';
const path = root + 'composition/';
const instances = {};
const files = fs.readdirSync(path);
const domain = '';//'https://static.jillix.com/';
const type = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
const dependencies = {};
const modules = [
    "flow-app",
    "flow-browser",
    "flow-http",
    "flow-pack",
    "flow-router",
    "flow-service-api",
    "flow-tools",
    "flow-static",
    "flow-schema",
    "flow-url",
    "flow-sendgrid",
    "flow-auth",
    "flow-view",
    "flow-api",
    "flow-remodal",
    "builder",
    "schema"
];

modules.forEach(dep => {

    let owner = 'jillix';
    switch (dep) {
        case 'flow-view':
        case 'flow-auth':
            owner = 'adioo';
            break;
    }

    write(
        '<' + owner + '/' + dep  + '>',
        'http://schema.jillix.net/vocab/gitRepository',
        '"\\"git+https://github.com/' + owner + '/' + dep + '.git\\""'
    );

    write(
        '<' + owner + '/' + dep  + '>',
        'http://schema.org/name',
        '"\\"' + dep + '\\""'
    );
});

files.forEach(file => {

    if (!suffixTest.test(file)) {
        return;
    }

    try {
        let instance = JSON.parse(fs.readFileSync(path + file));
        instances[instance.name] = instance;
    } catch (error) {
        throw new Error(path + file + '\n' + error);
    }
});

for (let instance in instances) {
    Convert(instances[instance]);
}

for (let from in dependencies) {
    for (let to in dependencies[from]) {
        write(from, 'http://schema.jillix.net/vocab/dependency', to);
    }
}

function write (subject, predicate, object) {
    process.stdout.write(subject + ' <' + predicate + '> ' + object + ' .\n');
}

function getModuleIri (instance, method) {
    let module = instances[instance].module;
    let owner = 'jillix';

    switch (module) {
        case 'flow-view':
        case 'flow-auth':
            owner = 'adioo';
            break;
    }

    if (method) {
        return '<' + owner + '/' + module + '#' + method + '>';
    } else {
        return '<' + owner + '/' + module + '>';
    }
}

function extendInstance (instance, path) {
    path = path.split('/');
    let parsed = {
        type: path[0][0]
    };
    path[0] = path[0].substr(1);

    if (path.length > 1) {
        parsed.instance = path[0];
        parsed.path = path[1];
    } else {
        parsed.instance = instance;
        parsed.path = path[0]
    }

    if (parsed.type !== '>') {
        parsed.path = getModuleIri(parsed.instance, parsed.path);
    } else {
        parsed.path = '<' + domain + parsed.instance + '/' + parsed.path + '>';
    }

    return parsed;
}

function UID (len) {
    len = len || 23;
    for (var i = 0, random = ''; i < len; ++i) {
        random += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[0 | Math.random() * 62];
    }
    return random;
}

function Convert (instance) {
    let instance_name = '<' + domain + instance.name + '>';

    if (instance.name) {
        write(
            instance_name,
            'http://schema.org/name',
            '"\\"' + instance.name + '\\""'
        );
    }

    write(
        instance_name,
        type,
        '<http://schema.jillix.net/vocab/ModuleInstanceConfig>'
    );

    // module
    if (instance.module) {
        write(
            instance_name,
            'http://schema.jillix.net/vocab/module',
            getModuleIri(instance.name)
        );
    }

    // roles
    if (instance.roles) {
        for (let role in instance.roles) {
            write(
                instance_name,
                'http://schema.jillix.net/vocab/roles',
                '"\\"' + role + '\\""'
            );
        }
    }

    // args
    if (instance.config) {
        write(
            instance_name,
            'http://schema.jillix.net/vocab/args',
            '"\\"' + JSON.stringify(instance.config).replace(/"/g, '\\"') + '\\""'
        );
    }

    //flow
    if (instance.flow) {
        for (let event in instance.flow) {
            let event_iri = '<' + domain + instance.name + '/' + event + '>';
            write(
                event_iri,
                'http://schema.org/name',
                '"\\"' + event + '\\""'
            );

            write(
                instance_name,
                'http://schema.jillix.net/vocab/event',
                event_iri
            );

            write(
                event_iri,
                type,
                '<http://schema.jillix.net/vocab/FlowEvent>'
            );

            // end event
            if (instance.flow[event].e) {
                write(
                    event_iri,
                    'http://schema.jillix.net/vocab/onEnd',
                    '<' + domain + instance.flow[event].e + '>'
                );
            }

            // error event
            if (instance.flow[event].r) {
                write(
                    event_iri,
                    'http://schema.jillix.net/vocab/onError',
                    '<' + domain + instance.flow[event].r + '>'
                );
            }

            // sequence
            if (instance.flow[event].d) {
                let previous;
                instance.flow[event].d.forEach((handler, index) => {

                    let handler_id = '_:' + UID(8);
                    let path;
                    let args;

                    write(
                        index === 0 ? event_iri : previous,
                        'http://schema.jillix.net/vocab/sequence',
                        handler_id
                    );
                    previous = handler_id;

                    if (typeof handler === 'string') {
                        path = handler;
                        args = null;
                    } else {
                        path = handler[0];
                        args = handler[1];
                    }

                    path = extendInstance(instance.name, path);
                    if (instance.name !== path.instance) {
                        dependencies[instance_name] = dependencies[instance_name] || {};
                        dependencies[instance_name]['<' + domain + path.instance + '>'] = 1;
                    }

                    write(
                        handler_id,
                        'http://schema.jillix.net/vocab/event',
                        event_iri
                    );

                    write(
                        handler_id,
                        type,
                        '<http://schema.jillix.net/vocab/Sequence>'
                    );

                    if (args) {
                        write(
                            handler_id,
                            'http://schema.jillix.net/vocab/args',
                            '"\\"' + JSON.stringify(args).replace(/"/g, '\\"') + '\\""'
                        );
                    }

                    if (path.type !== '>') {
                        write(
                            handler_id,
                            'http://schema.jillix.net/vocab/instance',
                            '<' + domain + path.instance + '>'
                        );
                    }

                    switch (path.type) {
                        case '.':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/onceHandler',
                                path.path
                            );
                            break;

                        case ':':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/dataHandler',
                                path.path
                            );
                            break;
                        case '*':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/streamHandler',
                                path.path
                            );
                            break;

                        case '>':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/emit',
                                path.path
                            );
                            break;
                    }
                });
            }
        }
    }
}
<commit_msg>add module type<commit_after>'use strict'

// TODO module descriptors
const suffixTest = /\.json$/;
const resolve = require('path').resolve;
const fs = require('fs');
const root = resolve(process.argv[2] || '/home/adioo/Repos') + '/';
const path = root + 'composition/';
const instances = {};
const files = fs.readdirSync(path);
const domain = '';//'https://static.jillix.com/';
const type = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
const dependencies = {};
const modules = [
    "flow-app",
    "flow-browser",
    "flow-http",
    "flow-pack",
    "flow-router",
    "flow-service-api",
    "flow-tools",
    "flow-static",
    "flow-schema",
    "flow-url",
    "flow-sendgrid",
    "flow-auth",
    "flow-view",
    "flow-api",
    "flow-remodal",
    "builder",
    "schema"
];

modules.forEach(dep => {

    let owner = 'jillix';
    switch (dep) {
        case 'flow-view':
        case 'flow-auth':
            owner = 'adioo';
            break;
    }

    write(
        '<' + owner + '/' + dep  + '>',
        'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
        '<http://schema.jillix.net/vocab/Module>'
    );

    write(
        '<' + owner + '/' + dep  + '>',
        'http://schema.jillix.net/vocab/gitRepository',
        '"\\"git+https://github.com/' + owner + '/' + dep + '.git\\""'
    );

    write(
        '<' + owner + '/' + dep  + '>',
        'http://schema.org/name',
        '"\\"' + dep + '\\""'
    );
});

files.forEach(file => {

    if (!suffixTest.test(file)) {
        return;
    }

    try {
        let instance = JSON.parse(fs.readFileSync(path + file));
        instances[instance.name] = instance;
    } catch (error) {
        throw new Error(path + file + '\n' + error);
    }
});

for (let instance in instances) {
    Convert(instances[instance]);
}

for (let from in dependencies) {
    for (let to in dependencies[from]) {
        write(from, 'http://schema.jillix.net/vocab/dependency', to);
    }
}

function write (subject, predicate, object) {
    process.stdout.write(subject + ' <' + predicate + '> ' + object + ' .\n');
}

function getModuleIri (instance, method) {
    let module = instances[instance].module;
    let owner = 'jillix';

    switch (module) {
        case 'flow-view':
        case 'flow-auth':
            owner = 'adioo';
            break;
    }

    if (method) {
        return '<' + owner + '/' + module + '#' + method + '>';
    } else {
        return '<' + owner + '/' + module + '>';
    }
}

function extendInstance (instance, path) {
    path = path.split('/');
    let parsed = {
        type: path[0][0]
    };
    path[0] = path[0].substr(1);

    if (path.length > 1) {
        parsed.instance = path[0];
        parsed.path = path[1];
    } else {
        parsed.instance = instance;
        parsed.path = path[0]
    }

    if (parsed.type !== '>') {
        parsed.path = getModuleIri(parsed.instance, parsed.path);
    } else {
        parsed.path = '<' + domain + parsed.instance + '/' + parsed.path + '>';
    }

    return parsed;
}

function UID (len) {
    len = len || 23;
    for (var i = 0, random = ''; i < len; ++i) {
        random += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[0 | Math.random() * 62];
    }
    return random;
}

function Convert (instance) {
    let instance_name = '<' + domain + instance.name + '>';

    if (instance.name) {
        write(
            instance_name,
            'http://schema.org/name',
            '"\\"' + instance.name + '\\""'
        );
    }

    write(
        instance_name,
        type,
        '<http://schema.jillix.net/vocab/ModuleInstanceConfig>'
    );

    // module
    if (instance.module) {
        write(
            instance_name,
            'http://schema.jillix.net/vocab/module',
            getModuleIri(instance.name)
        );
    }

    // roles
    if (instance.roles) {
        for (let role in instance.roles) {
            write(
                instance_name,
                'http://schema.jillix.net/vocab/roles',
                '"\\"' + role + '\\""'
            );
        }
    }

    // args
    if (instance.config) {
        write(
            instance_name,
            'http://schema.jillix.net/vocab/args',
            '"\\"' + JSON.stringify(instance.config).replace(/"/g, '\\"') + '\\""'
        );
    }

    //flow
    if (instance.flow) {
        for (let event in instance.flow) {
            let event_iri = '<' + domain + instance.name + '/' + event + '>';
            write(
                event_iri,
                'http://schema.org/name',
                '"\\"' + event + '\\""'
            );

            write(
                instance_name,
                'http://schema.jillix.net/vocab/event',
                event_iri
            );

            write(
                event_iri,
                type,
                '<http://schema.jillix.net/vocab/FlowEvent>'
            );

            // end event
            if (instance.flow[event].e) {
                write(
                    event_iri,
                    'http://schema.jillix.net/vocab/onEnd',
                    '<' + domain + instance.flow[event].e + '>'
                );
            }

            // error event
            if (instance.flow[event].r) {
                write(
                    event_iri,
                    'http://schema.jillix.net/vocab/onError',
                    '<' + domain + instance.flow[event].r + '>'
                );
            }

            // sequence
            if (instance.flow[event].d) {
                let previous;
                instance.flow[event].d.forEach((handler, index) => {

                    let handler_id = '_:' + UID(8);
                    let path;
                    let args;

                    write(
                        index === 0 ? event_iri : previous,
                        'http://schema.jillix.net/vocab/sequence',
                        handler_id
                    );
                    previous = handler_id;

                    if (typeof handler === 'string') {
                        path = handler;
                        args = null;
                    } else {
                        path = handler[0];
                        args = handler[1];
                    }

                    path = extendInstance(instance.name, path);
                    if (instance.name !== path.instance) {
                        dependencies[instance_name] = dependencies[instance_name] || {};
                        dependencies[instance_name]['<' + domain + path.instance + '>'] = 1;
                    }

                    write(
                        handler_id,
                        'http://schema.jillix.net/vocab/event',
                        event_iri
                    );

                    write(
                        handler_id,
                        type,
                        '<http://schema.jillix.net/vocab/Sequence>'
                    );

                    if (args) {
                        write(
                            handler_id,
                            'http://schema.jillix.net/vocab/args',
                            '"\\"' + JSON.stringify(args).replace(/"/g, '\\"') + '\\""'
                        );
                    }

                    if (path.type !== '>') {
                        write(
                            handler_id,
                            'http://schema.jillix.net/vocab/instance',
                            '<' + domain + path.instance + '>'
                        );
                    }

                    switch (path.type) {
                        case '.':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/onceHandler',
                                path.path
                            );
                            break;

                        case ':':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/dataHandler',
                                path.path
                            );
                            break;
                        case '*':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/streamHandler',
                                path.path
                            );
                            break;

                        case '>':
                            write(
                                handler_id,
                                'http://schema.jillix.net/vocab/emit',
                                path.path
                            );
                            break;
                    }
                });
            }
        }
    }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var fs = require('fs')
var path = require('path')
var execSync = require('child_process').execSync

console.log('Checking if jsreport installed')
try {
  fs.statSync(path.join(process.cwd(), 'node_modules', 'jsreport'))
} catch (e) {
  console.log('Installing the latest jsreport, this takes few minutes')
  execSync('npm install jsreport', { stdio: [0, 1, 2] })
}

function tryRequire (module) {
  try {
    return fs.statSync(module)
  } catch (e) {
    return false
  }
}

function installStudio (p) {
  console.log('Installing jsreport-studio dev dependencies at ' + p)
  return execSync('npm install', { stdio: [0, 1, 2], cwd: p })
}

function installStudioIfRequired (p) {
  var packageJson
  try {
    packageJson = JSON.parse(fs.readFileSync(path.join(p, 'package.json'), 'utf8'))
  } catch (e) {
    return
  }

  for (var k in packageJson.devDependencies) {
    if (!tryRequire(path.join(p, 'node_modules', k))) {
      // somehow npm install failes on EBUSY error if this field is not deleted
      delete packageJson._requiredBy
      fs.writeFileSync(path.join(p, 'package.json'), JSON.stringify(packageJson, null, 2), 'utf8')
      return installStudio(p)
    }
  }
}

console.log('Making sure jsreport-studio has dev dependencies installed')
installStudioIfRequired(path.join(process.cwd(), 'node_modules', 'jsreport', 'node_modules', 'jsreport-studio'))
installStudioIfRequired(path.join(process.cwd(), 'node_modules', 'jsreport-studio'))

console.log('Starting ...')

process.env.NODE_ENV = 'jsreport-development'
var jsreport = require(path.join(process.cwd(), 'node_modules', 'jsreport'))
jsreport().init().catch(function (e) {
  console.error(e)
})
<commit_msg>add run-only option to start command<commit_after>#!/usr/bin/env node
var fs = require('fs')
var path = require('path')
var execSync = require('child_process').execSync

var argv = yargs.options({
  'run-only': {
    type: 'boolean',
    default: false
  }
}).argv

console.log('Checking if jsreport installed')

try {
  fs.statSync(path.join(process.cwd(), 'node_modules', 'jsreport'))
} catch (e) {
  console.log('Installing the latest jsreport, this takes few minutes')
  execSync('npm install jsreport', { stdio: [0, 1, 2] })
}

function tryRequire (module) {
  try {
    return fs.statSync(module)
  } catch (e) {
    return false
  }
}

function installStudio (p) {
  console.log('Installing jsreport-studio dev dependencies at ' + p)
  return execSync('npm install', { stdio: [0, 1, 2], cwd: p })
}

function installStudioIfRequired (p) {
  var packageJson
  try {
    packageJson = JSON.parse(fs.readFileSync(path.join(p, 'package.json'), 'utf8'))
  } catch (e) {
    return
  }

  for (var k in packageJson.devDependencies) {
    if (!tryRequire(path.join(p, 'node_modules', k))) {
      // somehow npm install failes on EBUSY error if this field is not deleted
      delete packageJson._requiredBy
      fs.writeFileSync(path.join(p, 'package.json'), JSON.stringify(packageJson, null, 2), 'utf8')
      return installStudio(p)
    }
  }
}

if (!argv.runOnly) {
  console.log('Making sure jsreport-studio has dev dependencies installed')
  installStudioIfRequired(path.join(process.cwd(), 'node_modules', 'jsreport', 'node_modules', 'jsreport-studio'))
  installStudioIfRequired(path.join(process.cwd(), 'node_modules', 'jsreport-studio'))
}

console.log('Starting ...')

if (!argv.runOnly) {
  process.env.NODE_ENV = 'jsreport-development'
}

var jsreport = require(path.join(process.cwd(), 'node_modules', 'jsreport'))
jsreport().init().catch(function (e) {
  console.error(e)
})
<|endoftext|>