<commit_before>// special shoutout to Geoffrey Pursell for single-handedly making Pattern Lab Node Pattern Engines possible! aww thanks :)
'use strict';
const { existsSync } = require('fs');
const path = require('path');

const findModules = require('./findModules');

const engineMatcher = /^engine-(.*)$/;

const logger = require('./log');

const { resolvePackageFolder } = require('@pattern-lab/core/src/lib/resolver');

const enginesDirectories = [
  {
    displayName: 'the core',
    path: path.resolve(__dirname, '..', '..', 'node_modules'),
  },
  {
    displayName: 'the general node_modules directory',
    path: path.resolve(resolvePackageFolder('@pattern-lab/core'), '..', '..'),
  },
];

/**
 * Given a path: return the engine name if the path points to a valid engine
 * module directory, or false if it doesn't.
 * @param filePath
 * @returns Engine name if exists or FALSE
 */
function isEngineModule(filePath) {
  const baseName = path.basename(filePath);
  const engineMatch = baseName.match(engineMatcher);

  if (engineMatch) {
    return engineMatch[1];
  }
  return false;
}

/**
 * @name resolveEngines
 * @desc Creates an array of all available patternlab engines
 * @param {string} dir - The directory to search for engines and scoped engines)
 * @return {Array<Engine>} An array of engine objects
 */
function resolveEngines(dir) {
  // Guard against non-existent directories.
  if (!existsSync(dir)) {
    return []; // Silence is golden …
  }

  return findModules(dir, isEngineModule);
}

function findEngineModulesInDirectory(dir) {
  const foundEngines = resolveEngines(dir);
  return foundEngines;
}

//
// PatternEngines: the main export of this module
//
// It's an Object/hash of all loaded pattern engines, empty at first.  My
// intention here is to make this return an object that can be used to obtain
// any loaded PatternEngine by addressing them like this:
//
//   var PatternEngines = require('./pattern_engines/pattern_engines');
//   var Mustache = PatternEngines['mustache'];
//
// Object.create lets us create an object with a specified prototype. We want
// this here because we would like the object's "own properties" to include
// only the engine names so we can easily iterate over them; all the handy
// methods and properites below should therefore be on its prototype.

const PatternEngines = Object.create({
  /**
   * Load all pattern engines.
   * @param patternLabConfig
   * @memberof PatternEngines
   */
  loadAllEngines: function (patternLabConfig) {
    const self = this;

    // Try to load engines! We scan for engines at each path specified above. This
    // function is kind of a big deal.
    enginesDirectories.forEach(function (engineDirectory) {
      const enginesInThisDir = findEngineModulesInDirectory(
        engineDirectory.path
      );

      logger.debug(
        `Loading engines from ${engineDirectory.displayName}: ${engineDirectory.path} ...`
      );

      // find all engine-named things in this directory and try to load them,
      // unless it's already been loaded.
      enginesInThisDir.forEach(function (engineDiscovery) {
        let errorMessage;
        const successMessage = 'good to go';

        try {
          // Give it a try! load 'er up. But not if we already have,
          // of course.  Also pass the pattern lab config object into
          // the engine's closure scope so it can know things about
          // things.
          if (self[engineDiscovery.name]) {
            throw new Error('already loaded, skipping.');
          }
          self[engineDiscovery.name] = require(engineDiscovery.modulePath);
          if (
            typeof self[engineDiscovery.name].usePatternLabConfig === 'function'
          ) {
            self[engineDiscovery.name].usePatternLabConfig(patternLabConfig);
          }
          if (typeof self[engineDiscovery.name].spawnMeta === 'function') {
            self[engineDiscovery.name].spawnMeta(patternLabConfig);
          }
        } catch (err) {
          errorMessage = err.message;
        } finally {
          // report on the status of the engine, one way or another!
          logger.info(
            `Pattern Engine ${engineDiscovery.name}: ${
              errorMessage ? errorMessage : successMessage
            }`
          );
        }
      });
    });

    // Complain if for some reason we haven't loaded any engines.
    if (Object.keys(self).length === 0) {
      logger.error('No engines loaded! Something is seriously wrong.');
    }
    logger.debug(`Done loading engines`);
  },

  /**
   * Get engine name for pattern.
   * @memberof PatternEngines
   * @param pattern
   * @returns engine name matching pattern
   */
  getEngineNameForPattern: function (pattern) {
    // avoid circular dependency by putting this in here. TODO: is this slow?
    const of = require('./object_factory');
    if (
      pattern instanceof of.Pattern &&
      typeof pattern.fileExtension === 'string' &&
      pattern.fileExtension
    ) {
      //loop through known engines and find the one that supports the pattern's fileExtension
      const engineNames = Object.keys(this);
      for (let i = 0; i < engineNames.length; i++) {
        const engine = this[engineNames[i]];

        if (Array.isArray(engine.engineFileExtension)) {
          if (engine.engineFileExtension.includes(pattern.fileExtension)) {
            return engine.engineName;
          }
        } else {
          //this likely means the users engines are out of date. todo: tell them to upgrade
          if (engine.engineFileExtension === pattern.fileExtension) {
            return engine.engineName;
          }
        }
      }
    }

    // otherwise, assume it's a plain mustache template string and act
    // accordingly
    return 'mustache';
  },

  /**
   * Get engine for pattern.
   * @memberof PatternEngines
   * @param pattern
   * @returns name of engine for pattern
   */
  getEngineForPattern: function (pattern) {
    if (pattern.isPseudoPattern) {
      return this.getEngineForPattern(pattern.basePattern);
    } else {
      const engineName = this.getEngineNameForPattern(pattern);
      return this[engineName];
    }
  },

  /**
   * Combine all found engines into a single array of supported extensions.
   * @memberof PatternEngines
   * @returns Array all supported file extensions
   */
  getSupportedFileExtensions: function () {
    const engineNames = Object.keys(PatternEngines);
    const allEnginesExtensions = engineNames.map((engineName) => {
      return PatternEngines[engineName].engineFileExtension;
    });
    return [].concat.apply([], allEnginesExtensions);
  },

  /**
   * Check if fileExtension is supported.
   * @memberof PatternEngines
   * @param fileExtension
   * @returns Boolean
   */
  isFileExtensionSupported: function (fileExtension) {
    const supportedExtensions = PatternEngines.getSupportedFileExtensions();
    return supportedExtensions.lastIndexOf(fileExtension) !== -1;
  },

  /**
   * Given a filename, return a boolean: whether or not the filename indicates
   * that the file is pseudopattern JSON
   * @param filename
   * @return boolean
   */
  isPseudoPatternJSON: function (filename) {
    const extension = path.extname(filename);
    return extension === '.json' && filename.indexOf('~') > -1;
  },

  /**
   * Takes a filename string, not a full path; a basename (plus extension)
   * ignore _underscored patterns, dotfiles, and anything not recognized by a
   * loaded pattern engine. Pseudo-pattern .json files ARE considered to be
   * pattern files!
   *
   * @memberof PatternEngines
   * @param filename
   * @returns boolean
   */
  isPatternFile: function (filename) {
    // skip hidden patterns/files without a second thought
    const extension = path.extname(filename);
    if (
      filename.charAt(0) === '.' ||
      (extension === '.json' && !PatternEngines.isPseudoPatternJSON(filename))
    ) {
      return false;
    }

    // not a hidden pattern, let's dig deeper
    const supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions();
    return (
      supportedPatternFileExtensions.lastIndexOf(extension) !== -1 ||
      PatternEngines.isPseudoPatternJSON(filename)
    );
  },
});

module.exports = PatternEngines;
<commit_msg>Revert "refactor: optimized engines directory retrieval (#1359)" (#1363)<commit_after>// special shoutout to Geoffrey Pursell for single-handedly making Pattern Lab Node Pattern Engines possible! aww thanks :)
'use strict';
const { existsSync } = require('fs');
const path = require('path');

const findModules = require('./findModules');

const engineMatcher = /^engine-(.*)$/;

const logger = require('./log');

const enginesDirectories = [
  {
    displayName: 'the core',
    path: path.resolve(__dirname, '..', '..', 'node_modules'),
  },
  {
    displayName: 'the edition or test directory',
    path: path.join(process.cwd(), 'node_modules'),
  },
];

/**
 * Given a path: return the engine name if the path points to a valid engine
 * module directory, or false if it doesn't.
 * @param filePath
 * @returns Engine name if exists or FALSE
 */
function isEngineModule(filePath) {
  const baseName = path.basename(filePath);
  const engineMatch = baseName.match(engineMatcher);

  if (engineMatch) {
    return engineMatch[1];
  }
  return false;
}

/**
 * @name resolveEngines
 * @desc Creates an array of all available patternlab engines
 * @param {string} dir - The directory to search for engines and scoped engines)
 * @return {Array<Engine>} An array of engine objects
 */
function resolveEngines(dir) {
  // Guard against non-existent directories.
  if (!existsSync(dir)) {
    return []; // Silence is golden …
  }

  return findModules(dir, isEngineModule);
}

function findEngineModulesInDirectory(dir) {
  const foundEngines = resolveEngines(dir);
  return foundEngines;
}

//
// PatternEngines: the main export of this module
//
// It's an Object/hash of all loaded pattern engines, empty at first.  My
// intention here is to make this return an object that can be used to obtain
// any loaded PatternEngine by addressing them like this:
//
//   var PatternEngines = require('./pattern_engines/pattern_engines');
//   var Mustache = PatternEngines['mustache'];
//
// Object.create lets us create an object with a specified prototype. We want
// this here because we would like the object's "own properties" to include
// only the engine names so we can easily iterate over them; all the handy
// methods and properites below should therefore be on its prototype.

const PatternEngines = Object.create({
  /**
   * Load all pattern engines.
   * @param patternLabConfig
   * @memberof PatternEngines
   */
  loadAllEngines: function (patternLabConfig) {
    const self = this;

    // Try to load engines! We scan for engines at each path specified above. This
    // function is kind of a big deal.
    enginesDirectories.forEach(function (engineDirectory) {
      const enginesInThisDir = findEngineModulesInDirectory(
        engineDirectory.path
      );

      logger.debug(`Loading engines from ${engineDirectory.displayName}...`);

      // find all engine-named things in this directory and try to load them,
      // unless it's already been loaded.
      enginesInThisDir.forEach(function (engineDiscovery) {
        let errorMessage;
        const successMessage = 'good to go';

        try {
          // Give it a try! load 'er up. But not if we already have,
          // of course.  Also pass the pattern lab config object into
          // the engine's closure scope so it can know things about
          // things.
          if (self[engineDiscovery.name]) {
            throw new Error('already loaded, skipping.');
          }
          self[engineDiscovery.name] = require(engineDiscovery.modulePath);
          if (
            typeof self[engineDiscovery.name].usePatternLabConfig === 'function'
          ) {
            self[engineDiscovery.name].usePatternLabConfig(patternLabConfig);
          }
          if (typeof self[engineDiscovery.name].spawnMeta === 'function') {
            self[engineDiscovery.name].spawnMeta(patternLabConfig);
          }
        } catch (err) {
          errorMessage = err.message;
        } finally {
          // report on the status of the engine, one way or another!
          logger.info(
            `Pattern Engine ${engineDiscovery.name}: ${
              errorMessage ? errorMessage : successMessage
            }`
          );
        }
      });
    });

    // Complain if for some reason we haven't loaded any engines.
    if (Object.keys(self).length === 0) {
      logger.error('No engines loaded! Something is seriously wrong.');
    }
    logger.debug(`Done loading engines`);
  },

  /**
   * Get engine name for pattern.
   * @memberof PatternEngines
   * @param pattern
   * @returns engine name matching pattern
   */
  getEngineNameForPattern: function (pattern) {
    // avoid circular dependency by putting this in here. TODO: is this slow?
    const of = require('./object_factory');
    if (
      pattern instanceof of.Pattern &&
      typeof pattern.fileExtension === 'string' &&
      pattern.fileExtension
    ) {
      //loop through known engines and find the one that supports the pattern's fileExtension
      const engineNames = Object.keys(this);
      for (let i = 0; i < engineNames.length; i++) {
        const engine = this[engineNames[i]];

        if (Array.isArray(engine.engineFileExtension)) {
          if (engine.engineFileExtension.includes(pattern.fileExtension)) {
            return engine.engineName;
          }
        } else {
          //this likely means the users engines are out of date. todo: tell them to upgrade
          if (engine.engineFileExtension === pattern.fileExtension) {
            return engine.engineName;
          }
        }
      }
    }

    // otherwise, assume it's a plain mustache template string and act
    // accordingly
    return 'mustache';
  },

  /**
   * Get engine for pattern.
   * @memberof PatternEngines
   * @param pattern
   * @returns name of engine for pattern
   */
  getEngineForPattern: function (pattern) {
    if (pattern.isPseudoPattern) {
      return this.getEngineForPattern(pattern.basePattern);
    } else {
      const engineName = this.getEngineNameForPattern(pattern);
      return this[engineName];
    }
  },

  /**
   * Combine all found engines into a single array of supported extensions.
   * @memberof PatternEngines
   * @returns Array all supported file extensions
   */
  getSupportedFileExtensions: function () {
    const engineNames = Object.keys(PatternEngines);
    const allEnginesExtensions = engineNames.map((engineName) => {
      return PatternEngines[engineName].engineFileExtension;
    });
    return [].concat.apply([], allEnginesExtensions);
  },

  /**
   * Check if fileExtension is supported.
   * @memberof PatternEngines
   * @param fileExtension
   * @returns Boolean
   */
  isFileExtensionSupported: function (fileExtension) {
    const supportedExtensions = PatternEngines.getSupportedFileExtensions();
    return supportedExtensions.lastIndexOf(fileExtension) !== -1;
  },

  /**
   * Given a filename, return a boolean: whether or not the filename indicates
   * that the file is pseudopattern JSON
   * @param filename
   * @return boolean
   */
  isPseudoPatternJSON: function (filename) {
    const extension = path.extname(filename);
    return extension === '.json' && filename.indexOf('~') > -1;
  },

  /**
   * Takes a filename string, not a full path; a basename (plus extension)
   * ignore _underscored patterns, dotfiles, and anything not recognized by a
   * loaded pattern engine. Pseudo-pattern .json files ARE considered to be
   * pattern files!
   *
   * @memberof PatternEngines
   * @param filename
   * @returns boolean
   */
  isPatternFile: function (filename) {
    // skip hidden patterns/files without a second thought
    const extension = path.extname(filename);
    if (
      filename.charAt(0) === '.' ||
      (extension === '.json' && !PatternEngines.isPseudoPatternJSON(filename))
    ) {
      return false;
    }

    // not a hidden pattern, let's dig deeper
    const supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions();
    return (
      supportedPatternFileExtensions.lastIndexOf(extension) !== -1 ||
      PatternEngines.isPseudoPatternJSON(filename)
    );
  },
});

module.exports = PatternEngines;
<|endoftext|>


<commit_before>import axios from 'axios';

const baseUrl =
  process.env.NODE_ENV === 'development'
    ? 'http://localhost:9000/api'
    : 'https://wappuapp-backend-dev.herokuapp.com/api';

const api = axios.create({
  baseURL: baseUrl
});

const request = async (method, opts) => {
  const req = {
    method,
    url: opts.url,
    data: opts.data,
    headers: {
      'Content-Type': 'application/json',
      'x-user-uuid': 'web',
      authorization: localStorage.getItem('token')
    }
  };
  try {
    const response = await api.request(req);
    return response;
  } catch (err) {
    throw err.response.data;
  }
};

export const get = async opts => request('get', { url: opts.url });

export const put = async opts => request('put', { url: opts.url });

export const post = async opts => request('post', opts);

export const del = async opts => request('delete', opts);
<commit_msg>maybe?<commit_after>import axios from 'axios';

const baseUrl =
  process.env.NODE_ENV === 'development'
    ? 'http://localhost:9000/api'
    : process.env.REACT_APP_BACKEND_URI;

console.log(baseUrl);

const api = axios.create({
  baseURL: baseUrl
});

const request = async (method, opts) => {
  const req = {
    method,
    url: opts.url,
    data: opts.data,
    headers: {
      'Content-Type': 'application/json',
      'x-user-uuid': 'web',
      authorization: localStorage.getItem('token')
    }
  };
  try {
    const response = await api.request(req);
    return response;
  } catch (err) {
    throw err.response.data;
  }
};

export const get = async opts => request('get', { url: opts.url });

export const put = async opts => request('put', { url: opts.url });

export const post = async opts => request('post', opts);

export const del = async opts => request('delete', opts);
<|endoftext|>


<commit_before>"use strict";

const async = require("async");
const path = require("path");
const top_sub = require("./topology_local_subprocess");
const top_inproc = require("./topology_local_inprocess");

////////////////////////////////////////////////////////////////////

/** Class that perform redirection of messages after they are emited from nodes */
class OutputRouter {

    /** Constructor prepares the object before any information is received. */
    constructor() {
        this._sources = {};
    }

    /** This method registers binding between source and destination
     * @param {string} source - Name of source
     * @param {string} destination - Name of destination
     * @param {string} stream_id - Stream ID used for routing
     */
    register(source, destination, stream_id) {
        if (!this._sources[source]) {
            this._sources[source] = [];
        }
        this._sources[source].push({ destination: destination, stream_id: stream_id || null });
    }

    /** Returns list of names that are destinations for data, emitted by source.
     * @param {*} source - Name of source
     * @param {string} stream_id - Stream ID used for routing
     */
    getDestinationsForSource(source, stream_id) {
        if (!this._sources[source]) {
            return [];
        }
        return this._sources[source]
            .filter(x => { return x.stream_id == stream_id; })
            .map(x => x.destination);
    }
}

/** This class runs local topology */
class TopologyLocal {

    /** Constructor prepares the object before any information is received. */
    constructor() {
        this._spouts = [];
        this._bolts = [];
        this._config = null;
        this._heartbeatTimeout = 10000;
        this._router = new OutputRouter();

        this._isRunning = false;
        this._isShuttingDown = false;
        this._heartbeatTimer = null;
        this._heartbeatCallback = null;
    }

    /** Initialization that sets up internal structure and
     * starts underlaying processes.
     */
    init(config, callback) {
        let self = this;
        self._config = config;
        self._heartbeatTimeout = config.general.heartbeat;
        self._initContext((err, context) => {
            let tasks = [];
            self._config.bolts.forEach((bolt_config) => {
                if (bolt_config.disabled) {
                    return;
                }
                bolt_config.onEmit = (data, stream_id, callback) => {
                    self._redirect(bolt_config.name, data, stream_id, callback);
                };
                let bolt = null;
                if (bolt_config.type == "sys" || bolt_config.type == "inproc") {
                    bolt = new top_inproc.TopologyBoltInproc(bolt_config, context);
                } else {
                    bolt = new top_sub.TopologyBolt(bolt_config, context);
                }
                self._bolts.push(bolt);
                tasks.push((xcallback) => { bolt.init(xcallback); });
                for (let input of bolt_config.inputs) {
                    self._router.register(input.source, bolt_config.name, input.stream_id);
                }
            });
            self._config.spouts.forEach((spout_config) => {
                if (spout_config.disabled) {
                    return;
                }
                spout_config.onEmit = (data, stream_id, callback) => {
                    self._redirect(spout_config.name, data, stream_id, callback);
                };
                let spout = null;

                if (spout_config.type == "sys" || spout_config.type == "inproc") {
                    spout = new top_inproc.TopologySpoutInproc(spout_config, context);
                } else {
                    spout = new top_sub.TopologySpout(spout_config, context);
                }
                self._spouts.push(spout);
                tasks.push((xcallback) => { spout.init(xcallback); });
            });
            self._runHeartbeat();
            async.series(tasks, callback);
        });
    }

    /** Sends run signal to all spouts */
    run() {
        console.log("Local topology started");
        for (let spout of this._spouts) {
            spout.run();
        }
        this._isRunning = true;
    }

    /** Sends pause signal to all spouts */
    pause(callback) {
        for (let spout of this._spouts) {
            spout.pause();
        }
        this._isRunning = false;
        callback();
    }

    /** Sends shutdown signal to all child processes */
    shutdown(callback) {
        let self = this;
        self._isShuttingDown = true;
        if (self._heartbeatTimer) {
            clearInterval(self._heartbeatTimer);
            self._heartbeatCallback()
        };
        self.pause((err) => {
            let tasks = [];
            self._spouts.forEach((spout) => {
                tasks.push((xcallback) => {
                    spout.shutdown(xcallback);
                });
            });
            self._bolts.forEach((bolt) => {
                tasks.push((xcallback) => {
                    bolt.shutdown(xcallback);
                });
            });
            if (self._config.general.shutdown) {
                let shutdown_conf = self._config.general.shutdown;
                let dir = path.resolve(shutdown_conf.working_dir); // path may be relative to current working dir
                let module_path = path.join(dir, shutdown_conf.cmd);
                tasks.push((xcallback) => { require(module_path).shutdown(xcallback); });
            }
            async.series(tasks, callback);
        });
    }

    /** Runs heartbeat pump until this object shuts down */
    _runHeartbeat() {
        let self = this;
        async.whilst(
            () => {
                return !self._isShuttingDown;
            },
            (xcallback) => {
                self._heartbeatCallback = xcallback;
                self._heartbeatTimer = setTimeout(
                    () => {
                        if (self._isRunning) {
                            self._heartbeat();
                        }
                        xcallback();
                    },
                    self._heartbeatTimeout);
            },
            () => { }
        );
    }

    /** Sends heartbeat signal to all child processes */
    _heartbeat() {
        for (let spout of this._spouts) {
            spout.heartbeat();
        }
        for (let bolt of this._bolts) {
            bolt.heartbeat();
        }
    }

    /** This method redirects/broadcasts message from source to other nodes.
     * It is done in async/parallel manner.
     * @param {string} source - Name of the source that emitted this data
     * @param {Object} data - Data content of the message
     * @param {string} stream_id - Name of the stream that this data belongs to
     * @param {Function} callback - standard callback
     */
    _redirect(source, data, stream_id, callback) {
        let self = this;
        let destinations = self._router.getDestinationsForSource(source, stream_id);
        async.each(
            destinations,
            (destination, xcallback) => {
                let data_clone = {};
                Object.assign(data_clone, data);
                let bolt = self._getBolt(destination);
                bolt.receive(data_clone, stream_id, xcallback);
            },
            callback
        );
    }

    /** Find bolt with given name.
     * @param {string} name - Name of the bolt that we need to find
     */
    _getBolt(name) {
        let hits = this._bolts.filter(x => x.getName() == name);
        if (hits.length === 0) {
            return null;
        }
        return hits[0];
    }

    /** This method optionally runs context initialization code
     * and returns the context object.
     * @param {Function} callback - standard callback
     */
    _initContext(callback) {
        let self = this;
        if (self._config.general.initialization) {
            let init_conf = self._config.general.initialization;
            let dir = path.resolve(init_conf.working_dir); // path may be relative to current working dir
            let module_path = path.join(dir, init_conf.cmd);
            require(module_path).init(init_conf.init, (err, context) => {
                if (err) { return callback(err); }
                callback(null, context);
            });
        } else {
            callback(null, null);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////

exports.TopologyLocal = TopologyLocal;
<commit_msg>fixed comment<commit_after>"use strict";

const async = require("async");
const path = require("path");
const top_sub = require("./topology_local_subprocess");
const top_inproc = require("./topology_local_inprocess");

////////////////////////////////////////////////////////////////////

/** Class that performs redirection of messages after they are emited from nodes */
class OutputRouter {

    /** Constructor prepares the object before any information is received. */
    constructor() {
        this._sources = {};
    }

    /** This method registers binding between source and destination
     * @param {string} source - Name of source
     * @param {string} destination - Name of destination
     * @param {string} stream_id - Stream ID used for routing
     */
    register(source, destination, stream_id) {
        if (!this._sources[source]) {
            this._sources[source] = [];
        }
        this._sources[source].push({ destination: destination, stream_id: stream_id || null });
    }

    /** Returns list of names that are destinations for data, emitted by source.
     * @param {*} source - Name of source
     * @param {string} stream_id - Stream ID used for routing
     */
    getDestinationsForSource(source, stream_id) {
        if (!this._sources[source]) {
            return [];
        }
        return this._sources[source]
            .filter(x => { return x.stream_id == stream_id; })
            .map(x => x.destination);
    }
}

/** This class runs local topology */
class TopologyLocal {

    /** Constructor prepares the object before any information is received. */
    constructor() {
        this._spouts = [];
        this._bolts = [];
        this._config = null;
        this._heartbeatTimeout = 10000;
        this._router = new OutputRouter();

        this._isRunning = false;
        this._isShuttingDown = false;
        this._heartbeatTimer = null;
        this._heartbeatCallback = null;
    }

    /** Initialization that sets up internal structure and
     * starts underlaying processes.
     */
    init(config, callback) {
        let self = this;
        self._config = config;
        self._heartbeatTimeout = config.general.heartbeat;
        self._initContext((err, context) => {
            let tasks = [];
            self._config.bolts.forEach((bolt_config) => {
                if (bolt_config.disabled) {
                    return;
                }
                bolt_config.onEmit = (data, stream_id, callback) => {
                    self._redirect(bolt_config.name, data, stream_id, callback);
                };
                let bolt = null;
                if (bolt_config.type == "sys" || bolt_config.type == "inproc") {
                    bolt = new top_inproc.TopologyBoltInproc(bolt_config, context);
                } else {
                    bolt = new top_sub.TopologyBolt(bolt_config, context);
                }
                self._bolts.push(bolt);
                tasks.push((xcallback) => { bolt.init(xcallback); });
                for (let input of bolt_config.inputs) {
                    self._router.register(input.source, bolt_config.name, input.stream_id);
                }
            });
            self._config.spouts.forEach((spout_config) => {
                if (spout_config.disabled) {
                    return;
                }
                spout_config.onEmit = (data, stream_id, callback) => {
                    self._redirect(spout_config.name, data, stream_id, callback);
                };
                let spout = null;

                if (spout_config.type == "sys" || spout_config.type == "inproc") {
                    spout = new top_inproc.TopologySpoutInproc(spout_config, context);
                } else {
                    spout = new top_sub.TopologySpout(spout_config, context);
                }
                self._spouts.push(spout);
                tasks.push((xcallback) => { spout.init(xcallback); });
            });
            self._runHeartbeat();
            async.series(tasks, callback);
        });
    }

    /** Sends run signal to all spouts */
    run() {
        console.log("Local topology started");
        for (let spout of this._spouts) {
            spout.run();
        }
        this._isRunning = true;
    }

    /** Sends pause signal to all spouts */
    pause(callback) {
        for (let spout of this._spouts) {
            spout.pause();
        }
        this._isRunning = false;
        callback();
    }

    /** Sends shutdown signal to all child processes */
    shutdown(callback) {
        let self = this;
        self._isShuttingDown = true;
        if (self._heartbeatTimer) {
            clearInterval(self._heartbeatTimer);
            self._heartbeatCallback()
        };
        self.pause((err) => {
            let tasks = [];
            self._spouts.forEach((spout) => {
                tasks.push((xcallback) => {
                    spout.shutdown(xcallback);
                });
            });
            self._bolts.forEach((bolt) => {
                tasks.push((xcallback) => {
                    bolt.shutdown(xcallback);
                });
            });
            if (self._config.general.shutdown) {
                let shutdown_conf = self._config.general.shutdown;
                let dir = path.resolve(shutdown_conf.working_dir); // path may be relative to current working dir
                let module_path = path.join(dir, shutdown_conf.cmd);
                tasks.push((xcallback) => { require(module_path).shutdown(xcallback); });
            }
            async.series(tasks, callback);
        });
    }

    /** Runs heartbeat pump until this object shuts down */
    _runHeartbeat() {
        let self = this;
        async.whilst(
            () => {
                return !self._isShuttingDown;
            },
            (xcallback) => {
                self._heartbeatCallback = xcallback;
                self._heartbeatTimer = setTimeout(
                    () => {
                        if (self._isRunning) {
                            self._heartbeat();
                        }
                        xcallback();
                    },
                    self._heartbeatTimeout);
            },
            () => { }
        );
    }

    /** Sends heartbeat signal to all child processes */
    _heartbeat() {
        for (let spout of this._spouts) {
            spout.heartbeat();
        }
        for (let bolt of this._bolts) {
            bolt.heartbeat();
        }
    }

    /** This method redirects/broadcasts message from source to other nodes.
     * It is done in async/parallel manner.
     * @param {string} source - Name of the source that emitted this data
     * @param {Object} data - Data content of the message
     * @param {string} stream_id - Name of the stream that this data belongs to
     * @param {Function} callback - standard callback
     */
    _redirect(source, data, stream_id, callback) {
        let self = this;
        let destinations = self._router.getDestinationsForSource(source, stream_id);
        async.each(
            destinations,
            (destination, xcallback) => {
                let data_clone = {};
                Object.assign(data_clone, data);
                let bolt = self._getBolt(destination);
                bolt.receive(data_clone, stream_id, xcallback);
            },
            callback
        );
    }

    /** Find bolt with given name.
     * @param {string} name - Name of the bolt that we need to find
     */
    _getBolt(name) {
        let hits = this._bolts.filter(x => x.getName() == name);
        if (hits.length === 0) {
            return null;
        }
        return hits[0];
    }

    /** This method optionally runs context initialization code
     * and returns the context object.
     * @param {Function} callback - standard callback
     */
    _initContext(callback) {
        let self = this;
        if (self._config.general.initialization) {
            let init_conf = self._config.general.initialization;
            let dir = path.resolve(init_conf.working_dir); // path may be relative to current working dir
            let module_path = path.join(dir, init_conf.cmd);
            require(module_path).init(init_conf.init, (err, context) => {
                if (err) { return callback(err); }
                callback(null, context);
            });
        } else {
            callback(null, null);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////

exports.TopologyLocal = TopologyLocal;
<|endoftext|>


<commit_before>'use strict';

angular.module('simple-autocomplete', [])
	.directive('autocomplete', ['autocomplete-keys', '$window', function(Keys, $window) {
		return {
			template: '<input type="text" class="autocomplete-input"' +
							'ng-class="inputClass"' +
							'ng-model="searchTerm"' +
							'ng-keydown="keyDown($event)"' +
							'ng-blur="onBlur()" />' +

						'
' +
							'
' +
								'
' +
									'No matches' +
								'
' +

								'
' +
									'
' +
										'{{option[displayProperty]}}' +
									'
' +
								'
' +
							'
' +
						'
',
			restrict: 'E',
			scope: {
				options: '=',
				onSelect: '=',
				displayProperty: '=',
				inputClass: '@',
				clearInput: '@'
			},
			controller: function($scope){
				$scope.searchTerm = '';
				$scope.highlightedOption = null;
				$scope.showOptions = false;
				$scope.matchingOptions = [];
				$scope.hasMatches = false;
				$scope.selectedOption = null;

				$scope.isOptionSelected = function(option) {
					return option === $scope.highlightedOption;
				};

				$scope.processSearchTerm = function(term) {
					console.log('ch-ch-ch-changin');
					if (term.length > 0) {
						if ($scope.selectedOption) {
							if (term != $scope.selectedOption[$scope.displayProperty]) {
								$scope.selectedOption = null;
							} else {
								$scope.closeAndClear();
								return;
							}
						}

						var matchingOptions = $scope.findMatchingOptions(term);
						$scope.matchingOptions = matchingOptions;
						if (!$scope.matchingOptions.indexOf($scope.highlightedOption) != -1) {
							$scope.clearHighlight();
						}
						$scope.hasMatches = matchingOptions.length > 0;
						$scope.showOptions = true;
					} else {
						$scope.closeAndClear();
					}
				};

				$scope.findMatchingOptions = function(term) {
					return $scope.options.filter(function(option) {
						var lowerCaseOption = option[$scope.displayProperty].toLowerCase();
						var lowerCaseTerm = term.toLowerCase();
						return lowerCaseOption.indexOf(lowerCaseTerm) != -1;
					});
				};

				$scope.keyDown = function(e) {
					switch(e.which) {
						case Keys.upArrow:
							e.preventDefault();
							if ($scope.showOptions) {
								$scope.highlightPrevious();
							}
							break;
						case Keys.downArrow:
							e.preventDefault();
							if ($scope.showOptions) {
								$scope.highlightNext();
							} else {
								$scope.showOptions = true;
								if ($scope.selectedOption) {
									$scope.highlightedOption = $scope.selectedOption;
								}
							}
							break;
						case Keys.enter:
							e.preventDefault();
							$scope.selectOption($scope.highlightedOption);
							break;
						case Keys.escape:
							$scope.closeAndClear();
							break;
					}
				};

				$scope.$watch('searchTerm', function(term){
					$scope.processSearchTerm(term);
				});

				$scope.highlightNext = function() {
					if (!$scope.highlightedOption) {
						$scope.highlightedOption = $scope.matchingOptions[0];
					} else {
						var currentIndex = $scope.currentOptionIndex();
						var nextIndex = currentIndex + 1 == $scope.matchingOptions.length ? 0 : currentIndex + 1;
						$scope.highlightedOption = $scope.matchingOptions[nextIndex];
					}
				};

				$scope.highlightPrevious = function() {
					if (!$scope.highlightedOption) {
						$scope.highlightedOption = $scope.matchingOptions[$scope.matchingOptions.length - 1];
					} else {
						var currentIndex = $scope.currentOptionIndex();
						var previousIndex = currentIndex == 0 ? $scope.matchingOptions.length - 1 : currentIndex - 1;
						$scope.highlightedOption = $scope.matchingOptions[previousIndex];
					}
				};

				$scope.onOptionHover = function(option) {
					$scope.highlightedOption = option;
				};

				$scope.onOptionClick = function(option) {
					console.log('clicking on optin');
				};

				$scope.clearHighlight = function() {
					$scope.highlightedOption = null;
				};

				$scope.closeAndClear = function() {
					$scope.showOptions = false;
					$scope.clearHighlight();
				};

				$scope.selectOption = function(option) {
					console.log('selected the option');
					$scope.selectedOption = option;
					$scope.onSelect(option);

					if ($scope.clearInput != 'False' && $scope.clearInput != 'false') {
						$scope.searchTerm = '';
					} else {
						$scope.searchTerm = option[$scope.displayProperty];
					}
				};

				$scope.onBlur = function() {
					$scope.closeAndClear();
				};

				$scope.currentOptionIndex = function() {
					return $scope.matchingOptions.indexOf($scope.highlightedOption);
				};
			},
			link: function(scope, elem, attrs) {
				scope.optionWidth = '400px';
				var inputElement = elem.children('.autocomplete-input')[0];

				scope.setOptionWidth = function() {
					console.log(inputElement.offsetWidth);
					scope.$apply(function() {
						var pixelWidth = inputElement.offsetWidth > 400 ? 400 : inputElement.offsetWidth - 2;
						scope.optionWidth = pixelWidth + 'px';
					});
				};

				angular.element(document).ready(function() {
					scope.setOptionWidth();
				});

				angular.element($window).bind('resize', function() {
	                scope.setOptionWidth();
	            });
			}
		};
	}])

	.factory('autocomplete-keys', function() {
		return {
			upArrow: 38,
			downArrow: 40,
			enter: 13,
			escape: 27
		};
	});<commit_msg>hopefully a better way to adjust option width<commit_after>'use strict';

angular.module('simple-autocomplete', [])
	.directive('autocomplete', ['autocomplete-keys', '$window', function(Keys, $window) {
		return {
			template: '<input type="text" class="autocomplete-input"' +
							'ng-class="inputClass"' +
							'ng-model="searchTerm"' +
							'ng-keydown="keyDown($event)"' +
							'ng-blur="onBlur()" />' +

						'
' +
							'
' +
								'
' +
									'No matches' +
								'
' +

								'
' +
									'
' +
										'{{option[displayProperty]}}' +
									'
' +
								'
' +
							'
' +
						'
',
			restrict: 'E',
			scope: {
				options: '=',
				onSelect: '=',
				displayProperty: '=',
				inputClass: '@',
				clearInput: '@'
			},
			controller: function($scope){
				$scope.searchTerm = '';
				$scope.highlightedOption = null;
				$scope.showOptions = false;
				$scope.matchingOptions = [];
				$scope.hasMatches = false;
				$scope.selectedOption = null;

				$scope.isOptionSelected = function(option) {
					return option === $scope.highlightedOption;
				};

				$scope.processSearchTerm = function(term) {
					console.log('ch-ch-ch-changin');
					if (term.length > 0) {
						if ($scope.selectedOption) {
							if (term != $scope.selectedOption[$scope.displayProperty]) {
								$scope.selectedOption = null;
							} else {
								$scope.closeAndClear();
								return;
							}
						}

						var matchingOptions = $scope.findMatchingOptions(term);
						$scope.matchingOptions = matchingOptions;
						if (!$scope.matchingOptions.indexOf($scope.highlightedOption) != -1) {
							$scope.clearHighlight();
						}
						$scope.hasMatches = matchingOptions.length > 0;
						$scope.showOptions = true;
					} else {
						$scope.closeAndClear();
					}
				};

				$scope.findMatchingOptions = function(term) {
					return $scope.options.filter(function(option) {
						var lowerCaseOption = option[$scope.displayProperty].toLowerCase();
						var lowerCaseTerm = term.toLowerCase();
						return lowerCaseOption.indexOf(lowerCaseTerm) != -1;
					});
				};

				$scope.keyDown = function(e) {
					switch(e.which) {
						case Keys.upArrow:
							e.preventDefault();
							if ($scope.showOptions) {
								$scope.highlightPrevious();
							}
							break;
						case Keys.downArrow:
							e.preventDefault();
							if ($scope.showOptions) {
								$scope.highlightNext();
							} else {
								$scope.showOptions = true;
								if ($scope.selectedOption) {
									$scope.highlightedOption = $scope.selectedOption;
								}
							}
							break;
						case Keys.enter:
							e.preventDefault();
							$scope.selectOption($scope.highlightedOption);
							break;
						case Keys.escape:
							$scope.closeAndClear();
							break;
					}
				};

				$scope.$watch('searchTerm', function(term){
					$scope.processSearchTerm(term);
				});

				$scope.highlightNext = function() {
					if (!$scope.highlightedOption) {
						$scope.highlightedOption = $scope.matchingOptions[0];
					} else {
						var currentIndex = $scope.currentOptionIndex();
						var nextIndex = currentIndex + 1 == $scope.matchingOptions.length ? 0 : currentIndex + 1;
						$scope.highlightedOption = $scope.matchingOptions[nextIndex];
					}
				};

				$scope.highlightPrevious = function() {
					if (!$scope.highlightedOption) {
						$scope.highlightedOption = $scope.matchingOptions[$scope.matchingOptions.length - 1];
					} else {
						var currentIndex = $scope.currentOptionIndex();
						var previousIndex = currentIndex == 0 ? $scope.matchingOptions.length - 1 : currentIndex - 1;
						$scope.highlightedOption = $scope.matchingOptions[previousIndex];
					}
				};

				$scope.onOptionHover = function(option) {
					$scope.highlightedOption = option;
				};

				$scope.onOptionClick = function(option) {
					console.log('clicking on optin');
				};

				$scope.clearHighlight = function() {
					$scope.highlightedOption = null;
				};

				$scope.closeAndClear = function() {
					$scope.showOptions = false;
					$scope.clearHighlight();
				};

				$scope.selectOption = function(option) {
					console.log('selected the option');
					$scope.selectedOption = option;
					$scope.onSelect(option);

					if ($scope.clearInput != 'False' && $scope.clearInput != 'false') {
						$scope.searchTerm = '';
					} else {
						$scope.searchTerm = option[$scope.displayProperty];
					}
				};

				$scope.onBlur = function() {
					$scope.closeAndClear();
				};

				$scope.currentOptionIndex = function() {
					return $scope.matchingOptions.indexOf($scope.highlightedOption);
				};
			},
			link: function(scope, elem, attrs) {
				scope.optionWidth = '400px';
				var inputElement = elem.children('.autocomplete-input')[0];

				scope.setOptionWidth = function() {
					console.log(inputElement.offsetWidth);
					$timeout(function() {
						var pixelWidth = inputElement.offsetWidth > 400 ? 400 : inputElement.offsetWidth - 2;
						scope.optionWidth = pixelWidth + 'px';
					});
				};

				angular.element(document).ready(function() {
					scope.setOptionWidth();
				});

				angular.element($window).bind('resize', function() {
	                scope.setOptionWidth();
	            });
			}
		};
	}])

	.factory('autocomplete-keys', function() {
		return {
			upArrow: 38,
			downArrow: 40,
			enter: 13,
			escape: 27
		};
	});<|endoftext|>


<commit_before>'use strict';

/**
 * node sh/make-parts-list.js すると、
 * この内容をベースに存在する画像ファイルでitemsを補完。
 *
 * そして、models/parts.js ができる！
 *
 */
module.exports = {
  body: {
    tabName: 'カラダ',
    tabOrder: 1,
    tabGroup: 'BASE',
    selectType: 'COLOR',
    items: [/* { id: 1, path: './path' } */],
    COLORS: {
      1: 'FEECE4',
      2: 'FED8C1',
      3: 'FEC49F',
      4: '9D6B48',
      5: '79491F',
      6: '4E2C07',
      7: '41230F'
    }
  },

  hair: {
    tabName: 'カミ',
    tabOrder: 2,
    tabGroup: 'BASE',
    selectType: 'TYPE_COLOR',
    items: [],
    COLORS: {
      1:  'FD8424',
      2:  '0F4DFB',
      3:  'FC1999',
      4:  '3DEB2B',
      5:  'FED430',
      6:  '9D1FD8',
      7:  'FFF2C4',
      8:  '222124',
      9:  'DB0A16',
      10: 'FD97B8',
      11: 'D699FC',
      12: 'A4F7FE',
      13: '95FEE5',
      14: 'C5FEB8',
      15: 'FFFDA1',
      16: '53A3FC',
    }
  },

  brows: {
    tabName: 'マユ',
    tabOrder: 3,
    tabGroup: 'FACE',
    selectType: 'TYPE_COLOR',
    items: [/* { id: 1, items: [ { id: 1, path: './path' } ] } */],
    COLORS: {
      1:  'FD8424',
      2:  '0F4DFB',
      3:  'FC1999',
      4:  '3DEB2B',
      5:  'FED430',
      6:  '9D1FD8',
      7:  'FFF2C4',
      8:  '222124',
      9:  'DB0A16',
      10: 'FD97B8',
      11: 'D699FC',
      12: 'A4F7FE',
      13: '95FEE5',
      14: 'C5FEB8',
      15: 'FFFDA1',
      16: '53A3FC',
    }
  },

  eyes: {
    tabName: 'メ',
    tabOrder: 5,
    tabGroup: 'FACE',
    selectType: 'TYPE_COLOR',
    items: [],
    COLORS: {
      1: '383834',
      2: '5D3C36',
      3: 'C01594',
      4: 'F09925',
      5: 'E2D22E',
      6: '159167',
      7: '081EDC'
    }
  },

  mouth: {
    tabName: 'クチ',
    tabOrder: 6,
    tabGroup: 'FACE',
    selectType: 'TYPE',
    items: [],
  },

  hat: {
    tabName: 'アタマ',
    tabOrder: 7,
    tabGroup: 'GEAR',
    selectType: 'TYPE',
    items: []
  },

  clothes: {
    tabName: 'フク',
    tabOrder: 8,
    tabGroup: 'GEAR',
    selectType: 'TYPE',
    items: []
  },

  bg: {
    tabName: 'ハイケイ',
    tabOrder: 9,
    tabGroup: 'OTHERS',
    selectType: 'TYPE_COLOR',
    items: [],
    COLORS: {
      1:  '000000',
      2:  '00212F',
      3:  '0C1CB0',
      4:  '0091FF',
      5:  '2CFEED',
      6:  '42E62A',
      7:  'FEF035',
      8:  'FD9126',
      9:  'FD89C1',
      10: 'CD0814',
      11: 'ffffff'
    }
  }
};
<commit_msg>定数切り出し<commit_after>'use strict';

/**
 * node sh/make-parts-list.js すると、
 * この内容をベースに存在する画像ファイルでitemsを補完。
 *
 * そして、models/parts.js ができる！
 *
 */
const BODY_COLORS = {
  1: 'FEECE4',
  2: 'FED8C1',
  3: 'FEC49F',
  4: '9D6B48',
  5: '79491F',
  6: '4E2C07',
  7: '41230F',
};

const HAIR_COLORS = {
  1:  'FD8424',
  2:  '0F4DFB',
  3:  'FC1999',
  4:  '3DEB2B',
  5:  'FED430',
  6:  '9D1FD8',
  7:  'FFF2C4',
  8:  '222124',
  9:  'DB0A16',
  10: 'FD97B8',
  11: 'D699FC',
  12: 'A4F7FE',
  13: '95FEE5',
  14: 'C5FEB8',
  15: 'FFFDA1',
  16: '53A3FC',
};

const EYE_COLORS = {
  1: '383834',
  2: '5D3C36',
  3: 'C01594',
  4: 'F09925',
  5: 'E2D22E',
  6: '159167',
  7: '081EDC'
};

const BG_COLORS = {
  1:  '000000',
  2:  '00212F',
  3:  '0C1CB0',
  4:  '0091FF',
  5:  '2CFEED',
  6:  '42E62A',
  7:  'FEF035',
  8:  'FD9126',
  9:  'FD89C1',
  10: 'CD0814',
  11: 'ffffff'
};

module.exports = {
  body: {
    tabName: 'カラダ',
    tabOrder: 1,
    tabGroup: 'BASE',
    selectType: 'COLOR',
    items: [/* { id: 1, path: './path' } */],
    COLORS: BODY_COLORS
  },

  hair: {
    tabName: 'カミ',
    tabOrder: 2,
    tabGroup: 'BASE',
    selectType: 'TYPE_COLOR',
    items: [],
    COLORS: HAIR_COLORS
  },

  brows: {
    tabName: 'マユ',
    tabOrder: 3,
    tabGroup: 'FACE',
    selectType: 'TYPE_COLOR',
    items: [/* { id: 1, items: [ { id: 1, path: './path' } ] } */],
    COLORS: HAIR_COLORS
  },

  eyes: {
    tabName: 'メ',
    tabOrder: 5,
    tabGroup: 'FACE',
    selectType: 'TYPE_COLOR',
    items: [],
    COLORS: EYE_COLORS
  },

  mouth: {
    tabName: 'クチ',
    tabOrder: 6,
    tabGroup: 'FACE',
    selectType: 'TYPE',
    items: [],
  },

  hat: {
    tabName: 'アタマ',
    tabOrder: 7,
    tabGroup: 'GEAR',
    selectType: 'TYPE',
    items: []
  },

  clothes: {
    tabName: 'フク',
    tabOrder: 8,
    tabGroup: 'GEAR',
    selectType: 'TYPE',
    items: []
  },

  bg: {
    tabName: 'ハイケイ',
    tabOrder: 9,
    tabGroup: 'OTHERS',
    selectType: 'TYPE_COLOR',
    items: [],
    COLORS: BG_COLORS
  }
};
<|endoftext|>


<commit_before>
chrome.browserAction.onClicked.addListener(
    function(tab) {
        chrome.tabs.create({url:
            chrome.extension.getURL('newtab.html')});
    }
);
chrome.extension.onRequest.addListener(
    function(request, sender, sendResponse) {
        if(request.action == 'openui') {
        chrome.tabs.create({url:
            chrome.extension.getURL('newtab.html')});
        } else if(request.action == 'listwindows') {
            db.window.get('',function(tx, results){
                    console.log('sending windows back');
                    sendResponse(getWindows(results));
                });
        } else if(request.action == 'listtabs') {
            db.tab.get(request.condition,function(tx, results){
                    console.log('sending tabs back');
                    sendResponse(getTabs(results));
                });
        }
    }
);

function getWindows(results) {
    var warr = [];
    for(var i=0; i < results.rows.length; i++) {
        var w = results.rows.item(i);
        warr.push({
            wid : w.wid,
            title : w.title
        });
    }
    return warr;
}

function getTabs(results) {
    var tarr = [];
    for(var i=0; i < results.rows.length; i++) {
        var t = results.rows.item(i);
        tarr.push({
            tid : t.tid,
            wid : t.wid,
            title : t.title,
            url : t.url,
            faviconurl : t.faviconurl,
            index : t.index,
            parent : t.parent,
            depth : t.depth
        });
    }
    return tarr;
}

/*
 * Create initial data structure
 */

db.open();
db.clear();
chrome.windows.getAll(null, processWindows);

function processWindows(windows) {
    var wl = windows.length;
    for(var i=0; i < wl; i++) {
        var w = windows[i];

        db.put(new db.window(w.id, null));

        chrome.tabs.getAllInWindow(w.id, processTabs);
    }
}

function processTabs(tabs) {
    var tl = tabs.length;
    for(var i=0; i < tl; i++) {
        var t = tabs[i];
        t.favIconUrl = sanitizeFavIcon(t.favIconUrl);
        db.put(new db.tab(t.id, t.title, t.url, t.favIconUrl,
                            t.index, t.windowId));
    }
}
fallbackIcon = chrome.extension.getURL('images/icon28.png');
function sanitizeFavIcon(fi) {
    if(fi == undefined || fi == null || fi.length == 0) {
        return fallbackIcon;
    } else {
        return fi;
    }
}

var currentTab = null;
/*
 * Tab Event listeners
 */

chrome.tabs.onUpdated.addListener(
    // Update tab entry in our data model
    function(tid, changeInfo, tab) {
        tab.favIconUrl = sanitizeFavIcon(tab.favIconUrl);
        db.tab.update('url = ?, status =  ?, title = ?, faviconurl = ? ',
                    'WHERE tid = ?',
                    [tab.url, tab.status, tab.title, tab.favIconUrl, tid]);
        if(!/chrome-extension:\/\/.*\/newtab.html/.test(tab.url)) {
            triggerUIRefresh();
        }
    }
);

chrome.tabs.onSelectionChanged.addListener(
    function(tid, selectInfo) {
        // Update the current selected tab.
        // This will be the parent tab of newly created tabs
        currentTab = tid;
    }
);

chrome.tabs.onCreated.addListener(
    function(tab) {
        // Is this a new tab or has a URL already?
        // If it's a new tab: its depth is zero (root tab)
        // else: it's a child of currently (or previously) selected tab
        if(tab.url == 'chrome://newtab/') {
            var t = new db.tab(tab.id, tab.title, tab.url, tab.favIconUrl,
                            tab.index, tab.windowId, 0, 0);
        } else {
            var t = new db.tab(tab.id, tab.title, tab.url, tab.favIconUrl,
                            tab.index, tab.windowId, currentTab, 1); // TODO
        }
        db.put(t, function(tx, r) {console.log('tab put done');});
        if(!/chrome-extension:\/\/.*\/newtab.html/.test(tab.url)) {
            console.debug('CREATE: trigger UI refresh '+tab.url);
            triggerUIRefresh();
        }
    }
);
chrome.tabs.onRemoved.addListener(
    function(tid) {
        db.tab.del('WHERE tid = '+tid,
            function(tx, r) {console.log('tab del done');});
        console.debug('REMOVE: trigger UI refresh '+tid);
        triggerUIRefresh();
    }
);

function triggerUIRefresh() {
    db.tab.get('WHERE url LIKE \'chrome-extension://%/newtab.html\'',
        function(tx, r) {
            for(var i=0; i < r.rows.length; i++) {
                var tab = r.rows.item(i);
                chrome.tabs.sendRequest(tab.tid, { msg: "RELOAD" });
            }
        }
    );
}

chrome.tabs.onAttached.addListener(
    function(tid, attachInfo) {
        // Update our data model
        db.tab.update('wid = ?', 'WHERE tid = ?',
            [attachInfo.newWindowId, tid]);
        console.debug('ATTACHED: trigger UI refresh '+tid);
        triggerUIRefresh();
    }
);
chrome.tabs.onDetached.addListener(
    function(tid, detachInfo) {
        // Update our data model
    }
);
chrome.tabs.onMoved.addListener(
    function(tid, moveInfo) {
    }
);

/*
 * Window event listeners
 */
chrome.windows.onRemoved.addListener(
    function(wid) {
        db.window.del('WHERE wid = '+wid);
        db.tab.del('WHERE wid = '+wid);
        console.debug('WINREMOVE: trigger UI refresh '+wid);
        triggerUIRefresh();
    }
);
chrome.windows.onCreated.addListener(
    function(win) {
        db.put(new db.window(win.id, null));
        console.debug('WINCREATE: trigger UI refresh '+win.id);
        triggerUIRefresh();
    }
);
<commit_msg>properly record the parent and depth of newly created tab.<commit_after>
chrome.browserAction.onClicked.addListener(
    function(tab) {
        chrome.tabs.create({url:
            chrome.extension.getURL('newtab.html')});
    }
);
chrome.extension.onRequest.addListener(
    function(request, sender, sendResponse) {
        if(request.action == 'openui') {
        chrome.tabs.create({url:
            chrome.extension.getURL('newtab.html')});
        } else if(request.action == 'listwindows') {
            db.window.get('',function(tx, results){
                    console.log('sending windows back');
                    sendResponse(getWindows(results));
                });
        } else if(request.action == 'listtabs') {
            db.tab.get(request.condition,function(tx, results){
                    console.log('sending tabs back');
                    sendResponse(getTabs(results));
                });
        }
    }
);

function getWindows(results) {
    var warr = [];
    for(var i=0; i < results.rows.length; i++) {
        var w = results.rows.item(i);
        warr.push({
            wid : w.wid,
            title : w.title
        });
    }
    return warr;
}

function getTabs(results) {
    var tarr = [];
    for(var i=0; i < results.rows.length; i++) {
        var t = results.rows.item(i);
        tarr.push({
            tid : t.tid,
            wid : t.wid,
            title : t.title,
            url : t.url,
            faviconurl : t.faviconurl,
            index : t.index,
            parent : t.parent,
            depth : t.depth
        });
    }
    return tarr;
}

/*
 * Create initial data structure
 */

db.open();
db.clear();
chrome.windows.getAll(null, processWindows);

function processWindows(windows) {
    var wl = windows.length;
    for(var i=0; i < wl; i++) {
        var w = windows[i];

        db.put(new db.window(w.id, null));

        chrome.tabs.getAllInWindow(w.id, processTabs);
    }
}

function processTabs(tabs) {
    var tl = tabs.length;
    for(var i=0; i < tl; i++) {
        var t = tabs[i];
        t.favIconUrl = sanitizeFavIcon(t.favIconUrl);
        db.put(new db.tab(t.id, t.title, t.url, t.favIconUrl,
                            t.index, t.windowId));
    }
}
fallbackIcon = chrome.extension.getURL('images/icon28.png');
function sanitizeFavIcon(fi) {
    if(fi == undefined || fi == null || fi.length == 0) {
        return fallbackIcon;
    } else {
        return fi;
    }
}

var currentTab = null;
/*
 * Tab Event listeners
 */

chrome.tabs.onUpdated.addListener(
    // Update tab entry in our data model
    function(tid, changeInfo, tab) {
        tab.favIconUrl = sanitizeFavIcon(tab.favIconUrl);
        db.tab.update('url = ?, status =  ?, title = ?, faviconurl = ? ',
                    'WHERE tid = ?',
                    [tab.url, tab.status, tab.title, tab.favIconUrl, tid]);
        if(!/chrome-extension:\/\/.*\/newtab.html/.test(tab.url)) {
            triggerUIRefresh();
        }
    }
);

chrome.tabs.onSelectionChanged.addListener(
    function(tid, selectInfo) {
        // Update the current selected tab.
        // This will be the parent tab of newly created tabs
        db.tab.get('WHERE tid = '+tid, function(tx, r) {
                if(r.rows.length != 1) {
                    console.error('How many tabs u want? '+r.rows.length);
                    return;
                }
                var t = r.rows.item(0);
                currentTab = {
                    tid : t.tid,
                    title : t.title,
                    url : t.url,
                    faviconurl : t.faviconurl,
                    index : t.index,
                    wid : t.wid,
                    parent : t.parent,
                    depth : t.depth
                }
            });
    }
);

chrome.tabs.onCreated.addListener(
    function(tab) {
        // Is this a new tab or has a URL already?
        // If it's a new tab: its depth is zero (root tab)
        // else: it's a child of currently (or previously) selected tab
        if(tab.url == 'chrome://newtab/') {
            var t = new db.tab(tab.id, tab.title, tab.url, tab.favIconUrl,
                            tab.index, tab.windowId, 0, 0);
        } else {
            var t = new db.tab(tab.id, tab.title, tab.url, tab.favIconUrl,
                            tab.index, tab.windowId,
                            currentTab.tid, currentTab.depth+1);
        }
        db.put(t, function(tx, r) {console.log('tab put done');});
        if(!/chrome-extension:\/\/.*\/newtab.html/.test(tab.url)) {
            console.debug('CREATE: trigger UI refresh '+tab.url);
            triggerUIRefresh();
        }
    }
);
chrome.tabs.onRemoved.addListener(
    function(tid) {
        db.tab.del('WHERE tid = '+tid,
            function(tx, r) {console.log('tab del done');});
        console.debug('REMOVE: trigger UI refresh '+tid);
        triggerUIRefresh();
    }
);

function triggerUIRefresh() {
    db.tab.get('WHERE url LIKE \'chrome-extension://%/newtab.html\'',
        function(tx, r) {
            for(var i=0; i < r.rows.length; i++) {
                var tab = r.rows.item(i);
                chrome.tabs.sendRequest(tab.tid, { msg: "RELOAD" });
            }
        }
    );
}

chrome.tabs.onAttached.addListener(
    function(tid, attachInfo) {
        // Update our data model
        db.tab.update('wid = ?', 'WHERE tid = ?',
            [attachInfo.newWindowId, tid]);
        console.debug('ATTACHED: trigger UI refresh '+tid);
        triggerUIRefresh();
    }
);
chrome.tabs.onDetached.addListener(
    function(tid, detachInfo) {
        // Update our data model
    }
);
chrome.tabs.onMoved.addListener(
    function(tid, moveInfo) {
    }
);

/*
 * Window event listeners
 */
chrome.windows.onRemoved.addListener(
    function(wid) {
        db.window.del('WHERE wid = '+wid);
        db.tab.del('WHERE wid = '+wid);
        console.debug('WINREMOVE: trigger UI refresh '+wid);
        triggerUIRefresh();
    }
);
chrome.windows.onCreated.addListener(
    function(win) {
        db.put(new db.window(win.id, null));
        console.debug('WINCREATE: trigger UI refresh '+win.id);
        triggerUIRefresh();
    }
);
<|endoftext|>


<commit_before>(function() {
  'use strict';

  function sequoiaTreeDirective(Tree, Utils, BUTTONS, DEFAULT_OPTIONS, SORTABLE_OPTIONS){

    return {
      restrict: 'AE',
      replace: true,
      templateUrl: 'angular-sequoia.html',
      scope: {
        'treeNodes': '=sequoiaTree',
        'model': '=?ngModel',
        'template': '=?nodeTemplate',
        'options': '=?',
        'path': '=?sequoiaTreePath'
      },
      link: function(scope) {
        function init() {
          /* Set the default options*/
          scope.options = _.defaults(scope.options || {}, DEFAULT_OPTIONS);
          scope.canEdit = scope.options.canEdit;
          scope.inline = scope.options.inline;
          scope.allowSelect = scope.options.allowSelect;
          scope.isMultiSelect = scope.options.limit === 1 ? false : true;
          scope.breadcrumbs = { path: '', nodes: [] };
          scope.buttons = _.defaults(scope.options.buttons, BUTTONS);
          scope.sortableOptions = _.assign({}, SORTABLE_OPTIONS, {onSort: handleSort});
          scope.tree = new Tree(scope.treeNodes, scope.template, scope.buttons);

          scope.model = Utils.setModel(scope.isMultiSelect, scope.model);

          scope.containerStyle = !scope.inline ? { 'overflow': 'scroll', 'max-height': '400px' } : {};
        }

        function handleSort(evt) {
          if(scope.breadcrumbs.path.length) {
            scope.treeNodes = Utils.updateNodesInPath(scope.treeNodes, scope.breadcrumbs.path, evt.models, scope.tree.template.nodes);
          } else {
            scope.treeNodes = evt.models;
          }
        }

        function paginate() {
          scope.tree.paginate();
          scope.finished = scope.tree.pagination.finished;
        }

        scope.load = function(node) {
          scope.onlySelected = false;

          var n = node ? node : scope.path ? scope.path : null;

          if(scope.tree.isValidNode(n)) {
            scope.tree.setCurrentNodes(n[scope.tree.template.nodes]);
            scope.breadcrumbs = scope.tree.breadcrumbs(n[scope.tree.template.id]);
            scope.path = n;
            scope.parentNode = scope.tree.findParentNode(scope.breadcrumbs.nodes);
          } else {
            scope.tree.setCurrentNodes();
            scope.breadcrumbs = { path: '', nodes: [] };
            scope.parentNode = null;
            scope.path = null;
          }

          scope.tree.resetPagination();
          paginate();
          scope.$emit('nodes:updated');
        };

        scope.loadMore = function() {
          paginate();
        };

        scope.select = function(node) {
          //make sure that scope.model is setup
          if(_.isUndefined(scope.model)) {
            scope.model = Utils.setModel(scope.isMultiSelect, scope.model);
          }

          if(node[scope.tree.template.id]) {
            if(scope.options.limit !== 0 && scope.model.length === scope.options.limit) {
              scope.notification = 'You cannot select more than ' + scope.options.limit + ' items!';
            } else {
              if(scope.isMultiSelect) {
                scope.model.push(node[scope.tree.template.id]);
              } else {
                scope.model = node[scope.tree.template.id];
              }
            }
          }
        };

        scope.deselect = function(node) {
          if(scope.isMultiSelect) {
            var index = node[scope.tree.template.id] ? _.indexOf(scope.model,node[scope.tree.template.id]) : -1;
            if(index !== -1) {
              scope.model.splice(index, 1);
            }
          } else {
            scope.model = '';
          }

        };

        scope.deselectAll = function() {
          scope.model = scope.isMultiSelect ? [] : '';
        };

        scope.isSelected = function(node) {
          return scope.isMultiSelect ? _.indexOf(scope.model, node[scope.tree.template.id]) !== -1 ? true : false : scope.model === node[scope.tree.template.id];
        };

        scope.toggleSelected = function() {
          if(scope.onlySelected) {
            scope.onlySelected = false;
            scope.tree.setCurrentNodes(scope.tree.getNodesInPath());
          } else {
            scope.onlySelected = true;
            var selected = scope.tree.findSelected(scope.model);
            scope.tree.setNodesInPath(scope.tree.nodes);
            scope.tree.setCurrentNodes(selected);
          }

          paginate();
        };

        init();

        scope.$watchCollection('treeNodes', function(newVal) {
          if(newVal) {
            scope.tree = new Tree(scope.treeNodes, scope.template, scope.buttons);
            scope.load();
          }
        });

        scope.$watchCollection('path', function(newVal) {
          if(newVal) {
            scope.load();
          }
        });

        /* Handle Modal */
        scope.showModal = function() {
          scope.load();
          scope.modalShown = true;
        };

        scope.closeModal = function() {
          scope.modalShown = false;
        };

        /* Handle adding and editing nodes */
        scope.toggleEditing = function(form) {
          //handle form validation
          if(scope.isEditing) {
            form.isSubmitted = true;
          }
          if(form && !form.$valid) {
            return;
          }

          scope.treeNodes = scope.tree.tree;

          scope.isEditing = !scope.isEditing;
        };

        scope.addNode = function (node) {

          if (typeof node !== 'undefined') {
            // Because of the pruneTree function, we are removing the subnodes when we remove the last ever node, so we need to make sure it is still there when we add a new node
            node = Utils.ensureChildren(node, this.template);
          }

          if(scope.tree.isValidNode(node)) {
            scope.load(node);
          }

          scope.tree.addNode();
          paginate();

          scope.isEditing = true;
        };

        scope.remove = function(node) {
          scope.tree.removeNode(node);
          paginate();
        };

        scope.closeNotification = function() {
          scope.notification = '';
        };
      }
    };

  }

  sequoiaTreeDirective.$inject = ['SequoiaTree', 'SequoiaTreeUtils', 'BUTTONS', 'DEFAULT_OPTIONS', 'SORTABLE_OPTIONS'];

  angular.module('ngSequoia')
    .directive('sequoiaTree', sequoiaTreeDirective);

})();
<commit_msg>Fix go to parent node when removing last child<commit_after>(function() {
  'use strict';

  function sequoiaTreeDirective(Tree, Utils, BUTTONS, DEFAULT_OPTIONS, SORTABLE_OPTIONS){

    return {
      restrict: 'AE',
      replace: true,
      templateUrl: 'angular-sequoia.html',
      scope: {
        'treeNodes': '=sequoiaTree',
        'model': '=?ngModel',
        'template': '=?nodeTemplate',
        'options': '=?',
        'path': '=?sequoiaTreePath'
      },
      link: function(scope) {
        function init() {
          /* Set the default options*/
          scope.options = _.defaults(scope.options || {}, DEFAULT_OPTIONS);
          scope.canEdit = scope.options.canEdit;
          scope.inline = scope.options.inline;
          scope.allowSelect = scope.options.allowSelect;
          scope.isMultiSelect = scope.options.limit === 1 ? false : true;
          scope.breadcrumbs = { path: '', nodes: [] };
          scope.buttons = _.defaults(scope.options.buttons, BUTTONS);
          scope.sortableOptions = _.assign({}, SORTABLE_OPTIONS, { onSort: handleSort });
          scope.tree = new Tree(scope.treeNodes, scope.template, scope.buttons);

          scope.model = Utils.setModel(scope.isMultiSelect, scope.model);

          scope.containerStyle = !scope.inline ? { 'overflow': 'scroll', 'max-height': '400px' } : {};

          scope._cachedNode = null;
        }

        function handleSort(evt) {
          if(scope.breadcrumbs.path.length) {
            scope.treeNodes = Utils.updateNodesInPath(scope.treeNodes, scope.breadcrumbs.path, evt.models, scope.tree.template.nodes);
          } else {
            scope.treeNodes = evt.models;
          }
        }

        function paginate() {
          scope.tree.paginate();
          scope.finished = scope.tree.pagination.finished;
        }

        scope.load = function(node) {
          scope.onlySelected = false;

          var n = node ? node : scope.path ? scope.path : null;

          if (n && scope._cachedNode) {
            // We need to make sure the node has children
            n = Utils.ensureChildren(n, this.template);
            scope._cachedNode = null;
          }

          if(scope.tree.isValidNode(n)) {
            scope.tree.setCurrentNodes(n[scope.tree.template.nodes]);
            scope.breadcrumbs = scope.tree.breadcrumbs(n[scope.tree.template.id]);
            scope.path = n;
            scope.parentNode = scope.tree.findParentNode(scope.breadcrumbs.nodes);
          } else {
            scope.tree.setCurrentNodes();
            scope.breadcrumbs = { path: '', nodes: [] };
            scope.parentNode = null;
            scope.path = null;
          }

          scope.tree.resetPagination();
          paginate();
          scope.$emit('nodes:updated');
        };

        scope.loadMore = function() {
          paginate();
        };

        scope.select = function(node) {
          //make sure that scope.model is setup
          if(_.isUndefined(scope.model)) {
            scope.model = Utils.setModel(scope.isMultiSelect, scope.model);
          }

          if(node[scope.tree.template.id]) {
            if(scope.options.limit !== 0 && scope.model.length === scope.options.limit) {
              scope.notification = 'You cannot select more than ' + scope.options.limit + ' items!';
            } else {
              if(scope.isMultiSelect) {
                scope.model.push(node[scope.tree.template.id]);
              } else {
                scope.model = node[scope.tree.template.id];
              }
            }
          }
        };

        scope.deselect = function(node) {
          if(scope.isMultiSelect) {
            var index = node[scope.tree.template.id] ? _.indexOf(scope.model,node[scope.tree.template.id]) : -1;
            if(index !== -1) {
              scope.model.splice(index, 1);
            }
          } else {
            scope.model = '';
          }

        };

        scope.deselectAll = function() {
          scope.model = scope.isMultiSelect ? [] : '';
        };

        scope.isSelected = function(node) {
          return scope.isMultiSelect ? _.indexOf(scope.model, node[scope.tree.template.id]) !== -1 ? true : false : scope.model === node[scope.tree.template.id];
        };

        scope.toggleSelected = function() {
          if(scope.onlySelected) {
            scope.onlySelected = false;
            scope.tree.setCurrentNodes(scope.tree.getNodesInPath());
          } else {
            scope.onlySelected = true;
            var selected = scope.tree.findSelected(scope.model);
            scope.tree.setNodesInPath(scope.tree.nodes);
            scope.tree.setCurrentNodes(selected);
          }

          paginate();
        };

        init();

        scope.$watchCollection('treeNodes', function(newVal) {
          if(newVal) {
            scope.tree = new Tree(scope.treeNodes, scope.template, scope.buttons);
            scope.load();
          }
        });

        scope.$watchCollection('path', function (newVal) {
          if (newVal) {
            scope.load(scope._cachedNode);
          }
        });

        /* Handle Modal */
        scope.showModal = function() {
          scope.load();
          scope.modalShown = true;
        };

        scope.closeModal = function() {
          scope.modalShown = false;
        };

        /* Handle adding and editing nodes */
        scope.toggleEditing = function(form) {
          //handle form validation
          if(scope.isEditing) {
            form.isSubmitted = true;
          }
          if(form && !form.$valid) {
            return;
          }

          scope.treeNodes = scope.tree.tree;

          scope.isEditing = !scope.isEditing;
        };

        scope.addNode = function (node) {

          if (typeof node !== 'undefined') {
            // Because of the pruneTree function, we are removing the subnodes when we remove the last ever node, so we need to make sure it is still there when we add a new node
            node = Utils.ensureChildren(node, this.template);
          }

          if(scope.tree.isValidNode(node)) {
            scope.load(node);
          }

          scope.tree.addNode();
          paginate();

          scope.isEditing = true;
        };

        scope.remove = function (node) {
          node = Utils.ensureChildren(node, this.template);
          if (node[scope.tree.template.nodes].length < 1) {
            scope._cachedNode = scope.tree.findParentNode(scope.breadcrumbs.nodes);
          }

          scope.tree.removeNode(node);
        };

        scope.closeNotification = function() {
          scope.notification = '';
        };
      }
    };

  }

  sequoiaTreeDirective.$inject = ['SequoiaTree', 'SequoiaTreeUtils', 'BUTTONS', 'DEFAULT_OPTIONS', 'SORTABLE_OPTIONS'];

  angular.module('ngSequoia')
    .directive('sequoiaTree', sequoiaTreeDirective);

})();
<|endoftext|>


<commit_before>$.register({
  rule: [
    {
      host: /^1dl\.biz$/,
      path: /^\/(\w)\.php$/,
      query: /^\?([\d\/]+)$/,
    },
    {
      host: /^img\.1dl\.biz$/,
      path: /^\/(\w)\.php$/,
      query: /^\?\w\/([\d\/]+)$/,
    },
  ],
  ready: function () {
    'use strict';

    var a = $('.main a, .main-l a');
    $.openImage(a.href, {
      referer: true,
    });
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>1dl.biz<commit_after>$.register({
  rule: [
    {
      host: /^1dl\.biz$/,
      path: /^\/\w\.php$/,
      query: /^\?\w\/\d+$/,
    },
    {
      host: /^img\.1dl\.biz$/,
      path: /^\/\w\.php$/,
      query: /^\?\w\/([\d\/]+)$/,
    },
  ],
  ready: function () {
    'use strict';

    var a = $('.main a, .main-l a');
    $.openImage(a.href, {
      referer: true,
    });
  },
});

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>var regret = require('regret');

regret.add(
  'ctimeCase1',
  /\w{3} \w{3}  \d{1} \d{2}:\d{2}:\d{2}.\d{3}/,
  'Wed Mar  2 14:42:31.000'
);

regret.add(
  'ctimeCase2',
  /\w{3} \w{3} \d{2} \d{2}:\d{2}:\d{2}.\d{3}/,
  'Wed Mar 12 14:42:31.000'
);

regret.add(
  'ctime',
  /{{ctimeCase1}}|{{ctimeCase2}}/
);

regret.add(
  'ctimePreTwoPointFourCase1',
  /^\w{3} \w{3}  \d \d{2}:\d{2}:\d{2}/,
  'Wed Mar  2 14:42:31'
);

regret.add(
  'ctimePreTwoPointFourCase2',
  /^\w{3} \w{3} \d{2} \d{2}:\d{2}:\d{2}/,
  'Wed Mar 12 14:42:31'
);

regret.add(
  'ctimePreTwoPointFour',
  /{{ctimePreTwoPointFourCase1}}|{{ctimePreTwoPointFourCase2}}/
);

regret.add(
  'iso8601_local',
  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{4}/,
  '2014-02-13T18:00:04.709-0500'
);

regret.add(
  'iso8601_utc',
  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z/,
  '1970-01-01T00:00:00.000Z'
);

regret.add(
  'timestamp',
  new RegExp('({{ctime}}|{{ctimePreTwoPointFour}}|{{iso8601_local}}|' +
    '{{iso8601_utc}})')
);

regret.add(
  'mongodb.log',
  /^{{timestamp}} \[(\w+)\] (.*)/,
  '2014-02-13T18:00:04.709-0500 [initandlisten] db version v2.5.6-pre-',
  ['date', 'name', 'message']
);

regret.add(
  'mongodb.logshutdown',
  /(\w+)\: (.*)/,
  'dbexit: really exiting now',
  ['name', 'message']
);

module.exports = regret;<commit_msg>making the regex shorter<commit_after>var regret = require('regret');

regret.add(
  'ctimeCase1',
  /\w{3} \w{3}  \d \d{2}:\d{2}:\d{2}.\d{3}/,
  'Wed Mar  2 14:42:31.000'
);

regret.add(
  'ctimeCase2',
  /\w{3} \w{3} \d{2} \d{2}:\d{2}:\d{2}.\d{3}/,
  'Wed Mar 12 14:42:31.000'
);

regret.add(
  'ctime',
  /{{ctimeCase1}}|{{ctimeCase2}}/
);

regret.add(
  'ctimePreTwoPointFourCase1',
  /^\w{3} \w{3}  \d \d{2}:\d{2}:\d{2}/,
  'Wed Mar  2 14:42:31'
);

regret.add(
  'ctimePreTwoPointFourCase2',
  /^\w{3} \w{3} \d{2} \d{2}:\d{2}:\d{2}/,
  'Wed Mar 12 14:42:31'
);

regret.add(
  'ctimePreTwoPointFour',
  /{{ctimePreTwoPointFourCase1}}|{{ctimePreTwoPointFourCase2}}/
);

regret.add(
  'iso8601_local',
  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{4}/,
  '2014-02-13T18:00:04.709-0500'
);

regret.add(
  'iso8601_utc',
  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z/,
  '1970-01-01T00:00:00.000Z'
);

regret.add(
  'timestamp',
  new RegExp('({{ctime}}|{{ctimePreTwoPointFour}}|{{iso8601_local}}|' +
    '{{iso8601_utc}})')
);

regret.add(
  'mongodb.log',
  /^{{timestamp}} \[(\w+)\] (.*)/,
  '2014-02-13T18:00:04.709-0500 [initandlisten] db version v2.5.6-pre-',
  ['date', 'name', 'message']
);

regret.add(
  'mongodb.logshutdown',
  /(\w+)\: (.*)/,
  'dbexit: really exiting now',
  ['name', 'message']
);

module.exports = regret;<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.script',
  name: 'Script',

  implements: [
    'foam.nanos.auth.EnabledAware',
    'foam.nanos.auth.LastModifiedByAware'
  ],

  requires: [
    'foam.nanos.script.ScriptStatus',
    'foam.nanos.notification.notifications.ScriptRunNotification'
  ],

  imports: [
    'notificationDAO',
    'scriptDAO',
    'user'
  ],

  javaImports: [
    'bsh.EvalError',
    'bsh.Interpreter',
    'foam.core.*',
    'foam.dao.*',
    'foam.nanos.logger.Logger',
    'foam.nanos.auth.*',
    'foam.nanos.pm.PM',
    'java.io.ByteArrayOutputStream',
    'java.io.PrintStream',
    'java.util.Date',
    'static foam.mlang.MLang.*',
  ],

  tableColumns: [
    'id', 'server', 'description', 'lastDuration', 'status', 'run'
  ],

  searchColumns: ['id', 'description'],

  constants: [
    {
      name: 'MAX_OUTPUT_CHARS',
      type: 'Integer',
      value: 20000
    },
    {
      name: 'MAX_NOTIFICATION_OUTPUT_CHARS',
      type: 'Integer',
      value: 200
    }
  ],

  properties: [
    {
      class: 'String',
      name: 'id',
      tableWidth: 280
    },
    {
      class: 'Boolean',
      name: 'enabled',
      documentation: 'Enables script.',
      tableCellFormatter: function(value) {
        this.start()
          .style({ color: value ? 'green' : 'gray' })
          .add(value ? 'Y' : 'N')
        .end();
      },
      tableWidth: 90,
      value: true
    },
    {
      class: 'String',
      name: 'description',
      documentation: 'Description of the script.',
      tableWidth: 200
    },
    {
      class: 'DateTime',
      name: 'lastRun',
      documentation: 'Date and time the script ran last.',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      tableWidth: 140
    },
    {
      class: 'Duration',
      name: 'lastDuration',
      documentation: 'Date and time the script took to complete.',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      tableWidth: 125
    },
    /*
    {
      class: 'Enum',
      of: 'foam.nanos.script.Language',
      name: 'language',
      value: foam.nanos.script.Language.BEANSHELL,
      transient: true
      // TODO: fix JS support
    },
    */
    {
      class: 'Boolean',
      name: 'server',
      documentation: 'Runs on server side if enabled.',
      value: true,
      tableWidth: 80
    },
    {
      class: 'foam.core.Enum',
      of: 'foam.nanos.script.ScriptStatus',
      name: 'status',
      documentation: 'Status of script.',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      value: 'UNSCHEDULED',
      javaValue: 'ScriptStatus.UNSCHEDULED',
      tableWidth: 100,
      storageTransient: true
    },
    {
      class: 'Code',
      name: 'code'
    },
    {
      class: 'String',
      name: 'output',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      view: {
        class: 'foam.u2.view.ModeAltView',
        readView: { class: 'foam.u2.view.PreView' }
      },
      preSet: function(_, newVal) {
        // for client side scripts
        if ( newVal.length > this.MAX_OUTPUT_CHARS ) {
          newVal = newVal.substring(0, this.MAX_OUTPUT_CHARS) + '...';
        }
        return newVal;
      },
      javaSetter: `
      // for server side scripts
      if (val.length() > MAX_OUTPUT_CHARS) {
        val = val.substring(0, MAX_OUTPUT_CHARS) + "...";
      }
      output_ = val;
      outputIsSet_ = true;
      `
    },
    {
      class: 'String',
      name: 'notes',
      view: { class: 'foam.u2.tag.TextArea', rows: 4, cols: 144 }
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'lastModifiedBy',
      documentation: 'User who last modified script'
    }
  ],

  methods: [
    {
      name: 'createInterpreter',
      args: [
        { name: 'x', type: 'Context' }
      ],
      javaType: 'Interpreter',
      javaCode: `
        Interpreter shell = new Interpreter();

        try {
          shell.set("currentScript", this);
          shell.set("x", x);
          shell.eval("runScript(String name) { script = x.get(\\"scriptDAO\\").find(name); if ( script != null ) eval(script.code); }");
          shell.eval("foam.core.X sudo(String user) { foam.util.Auth.sudo(x, (String) user); }");
          shell.eval("foam.core.X sudo(Object id) { foam.util.Auth.sudo(x, id); }");
        } catch (EvalError e) {}

        return shell;
      `
    },
    {
      name: 'runScript',
      code: function() {
        var log = function() {
          this.output += Array.from(arguments).join('') + '\n';
        }.bind(this);
        try {
          with ({ log: log, print: log, x: this.__context__ })
          return Promise.resolve(eval(this.code));
        } catch (err) {
          this.output += err;
          return Promise.reject(err);
        }
      },
      args: [
        {
          name: 'x', type: 'Context'
        }
      ],
      javaCode: `
        ByteArrayOutputStream baos  = new ByteArrayOutputStream();
        PrintStream           ps    = new PrintStream(baos);
        Interpreter           shell = createInterpreter(x);
        PM                    pm    = new PM.Builder(x).setClassType(Script.getOwnClassInfo()).setName(getId()).build();

        // TODO: import common packages like foam.core.*, foam.dao.*, etc.
        try {
          setOutput("");
          shell.setOut(ps);
          shell.eval(getCode());
        } catch (Throwable e) {
          ps.println();
          e.printStackTrace(ps);
          Logger logger = (Logger) getX().get("logger");
          logger.error(e);
        } finally {
          pm.log(x);
        }

        setLastRun(new Date());
        setLastDuration(pm.getTime());
        ps.flush();
        setOutput(baos.toString());
    `
    },
    {
      name: 'poll',
      code: function() {
        var self = this;
        var interval = setInterval(function() {
            self.scriptDAO.find(self.id).then(function(script) {
              if ( script.status !== self.ScriptStatus.RUNNING ) {
                self.copyFrom(script);
                clearInterval(interval);

                // create notification
                var notification = self.ScriptRunNotification.create({
                  userId: self.user.id,
                  scriptId: script.id,
                  notificationType: 'Script Execution',
                  body: `Status: ${script.status}
                        Script Output: ${script.length > self.MAX_NOTIFICATION_OUTPUT_CHARS ?
                          script.output.substring(0, self.MAX_NOTIFICATION_OUTPUT_CHARS) + '...' :
                          script.output }
                        LastDuration: ${script.lastDuration}`
                });
                self.notificationDAO.put(notification);
              }
            }).catch(function() {
               clearInterval(interval);
              });
        }, 2000);
      }
    }
  ],

  actions: [
    {
      name: 'run',
      tableWidth: 70,
      confirmationRequired: true,
      code: function() {
        var self = this;
        this.output = '';
        this.status = this.ScriptStatus.SCHEDULED;
        if ( this.server ) {
          this.scriptDAO.put(this).then(function(script) {
              self.copyFrom(script);
              if ( script.status === self.ScriptStatus.RUNNING ) {
                self.poll();
              }
          });
        } else {
          this.status = this.ScriptStatus.RUNNING;
          this.runScript().then(() => {
            this.status = this.ScriptStatus.UNSCHEDULED;
            this.scriptDAO.put(this);
          }).catch((err) => {
            console.log(err);
            this.status = this.ScriptStatus.ERROR;
            this.scriptDAO.put(this);
          });
        }
      }
    }
  ]
});
<commit_msg>Get logger from x rather than getX<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.script',
  name: 'Script',

  implements: [
    'foam.nanos.auth.EnabledAware',
    'foam.nanos.auth.LastModifiedByAware'
  ],

  requires: [
    'foam.nanos.script.ScriptStatus',
    'foam.nanos.notification.notifications.ScriptRunNotification'
  ],

  imports: [
    'notificationDAO',
    'scriptDAO',
    'user'
  ],

  javaImports: [
    'bsh.EvalError',
    'bsh.Interpreter',
    'foam.core.*',
    'foam.dao.*',
    'foam.nanos.logger.Logger',
    'foam.nanos.auth.*',
    'foam.nanos.pm.PM',
    'java.io.ByteArrayOutputStream',
    'java.io.PrintStream',
    'java.util.Date',
    'static foam.mlang.MLang.*',
  ],

  tableColumns: [
    'id', 'server', 'description', 'lastDuration', 'status', 'run'
  ],

  searchColumns: ['id', 'description'],

  constants: [
    {
      name: 'MAX_OUTPUT_CHARS',
      type: 'Integer',
      value: 20000
    },
    {
      name: 'MAX_NOTIFICATION_OUTPUT_CHARS',
      type: 'Integer',
      value: 200
    }
  ],

  properties: [
    {
      class: 'String',
      name: 'id',
      tableWidth: 280
    },
    {
      class: 'Boolean',
      name: 'enabled',
      documentation: 'Enables script.',
      tableCellFormatter: function(value) {
        this.start()
          .style({ color: value ? 'green' : 'gray' })
          .add(value ? 'Y' : 'N')
        .end();
      },
      tableWidth: 90,
      value: true
    },
    {
      class: 'String',
      name: 'description',
      documentation: 'Description of the script.',
      tableWidth: 200
    },
    {
      class: 'DateTime',
      name: 'lastRun',
      documentation: 'Date and time the script ran last.',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      tableWidth: 140
    },
    {
      class: 'Duration',
      name: 'lastDuration',
      documentation: 'Date and time the script took to complete.',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      tableWidth: 125
    },
    /*
    {
      class: 'Enum',
      of: 'foam.nanos.script.Language',
      name: 'language',
      value: foam.nanos.script.Language.BEANSHELL,
      transient: true
      // TODO: fix JS support
    },
    */
    {
      class: 'Boolean',
      name: 'server',
      documentation: 'Runs on server side if enabled.',
      value: true,
      tableWidth: 80
    },
    {
      class: 'foam.core.Enum',
      of: 'foam.nanos.script.ScriptStatus',
      name: 'status',
      documentation: 'Status of script.',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      value: 'UNSCHEDULED',
      javaValue: 'ScriptStatus.UNSCHEDULED',
      tableWidth: 100,
      storageTransient: true
    },
    {
      class: 'Code',
      name: 'code'
    },
    {
      class: 'String',
      name: 'output',
      createMode: 'HIDDEN',
      updateMode: 'RO',
      view: {
        class: 'foam.u2.view.ModeAltView',
        readView: { class: 'foam.u2.view.PreView' }
      },
      preSet: function(_, newVal) {
        // for client side scripts
        if ( newVal.length > this.MAX_OUTPUT_CHARS ) {
          newVal = newVal.substring(0, this.MAX_OUTPUT_CHARS) + '...';
        }
        return newVal;
      },
      javaSetter: `
      // for server side scripts
      if (val.length() > MAX_OUTPUT_CHARS) {
        val = val.substring(0, MAX_OUTPUT_CHARS) + "...";
      }
      output_ = val;
      outputIsSet_ = true;
      `
    },
    {
      class: 'String',
      name: 'notes',
      view: { class: 'foam.u2.tag.TextArea', rows: 4, cols: 144 }
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'lastModifiedBy',
      documentation: 'User who last modified script'
    }
  ],

  methods: [
    {
      name: 'createInterpreter',
      args: [
        { name: 'x', type: 'Context' }
      ],
      javaType: 'Interpreter',
      javaCode: `
        Interpreter shell = new Interpreter();

        try {
          shell.set("currentScript", this);
          shell.set("x", x);
          shell.eval("runScript(String name) { script = x.get(\\"scriptDAO\\").find(name); if ( script != null ) eval(script.code); }");
          shell.eval("foam.core.X sudo(String user) { foam.util.Auth.sudo(x, (String) user); }");
          shell.eval("foam.core.X sudo(Object id) { foam.util.Auth.sudo(x, id); }");
        } catch (EvalError e) {}

        return shell;
      `
    },
    {
      name: 'runScript',
      code: function() {
        var log = function() {
          this.output += Array.from(arguments).join('') + '\n';
        }.bind(this);
        try {
          with ({ log: log, print: log, x: this.__context__ })
          return Promise.resolve(eval(this.code));
        } catch (err) {
          this.output += err;
          return Promise.reject(err);
        }
      },
      args: [
        {
          name: 'x', type: 'Context'
        }
      ],
      javaCode: `
        ByteArrayOutputStream baos  = new ByteArrayOutputStream();
        PrintStream           ps    = new PrintStream(baos);
        Interpreter           shell = createInterpreter(x);
        PM                    pm    = new PM.Builder(x).setClassType(Script.getOwnClassInfo()).setName(getId()).build();

        // TODO: import common packages like foam.core.*, foam.dao.*, etc.
        try {
          setOutput("");
          shell.setOut(ps);
          shell.eval(getCode());
        } catch (Throwable e) {
          ps.println();
          e.printStackTrace(ps);
          Logger logger = (Logger) x.get("logger");
          logger.error(e);
        } finally {
          pm.log(x);
        }

        setLastRun(new Date());
        setLastDuration(pm.getTime());
        ps.flush();
        setOutput(baos.toString());
    `
    },
    {
      name: 'poll',
      code: function() {
        var self = this;
        var interval = setInterval(function() {
            self.scriptDAO.find(self.id).then(function(script) {
              if ( script.status !== self.ScriptStatus.RUNNING ) {
                self.copyFrom(script);
                clearInterval(interval);

                // create notification
                var notification = self.ScriptRunNotification.create({
                  userId: self.user.id,
                  scriptId: script.id,
                  notificationType: 'Script Execution',
                  body: `Status: ${script.status}
                        Script Output: ${script.length > self.MAX_NOTIFICATION_OUTPUT_CHARS ?
                          script.output.substring(0, self.MAX_NOTIFICATION_OUTPUT_CHARS) + '...' :
                          script.output }
                        LastDuration: ${script.lastDuration}`
                });
                self.notificationDAO.put(notification);
              }
            }).catch(function() {
               clearInterval(interval);
              });
        }, 2000);
      }
    }
  ],

  actions: [
    {
      name: 'run',
      tableWidth: 70,
      confirmationRequired: true,
      code: function() {
        var self = this;
        this.output = '';
        this.status = this.ScriptStatus.SCHEDULED;
        if ( this.server ) {
          this.scriptDAO.put(this).then(function(script) {
              self.copyFrom(script);
              if ( script.status === self.ScriptStatus.RUNNING ) {
                self.poll();
              }
          });
        } else {
          this.status = this.ScriptStatus.RUNNING;
          this.runScript().then(() => {
            this.status = this.ScriptStatus.UNSCHEDULED;
            this.scriptDAO.put(this);
          }).catch((err) => {
            console.log(err);
            this.status = this.ScriptStatus.ERROR;
            this.scriptDAO.put(this);
          });
        }
      }
    }
  ]
});
<|endoftext|>