<commit_before>/* globals requirejs, require */

import Ember from 'ember';
import { assert, deprecate, warn } from '@ember/debug';
import EmberObject, { get, computed } from '@ember/object';
import { dasherize, classify, underscore } from '@ember/string';
import { DEBUG } from '@glimmer/env';
import classFactory from '../../utils/class-factory';

if (typeof requirejs.entries === 'undefined') {
  requirejs.entries = requirejs._eak_seen;
}

export class ModuleRegistry {
  constructor(entries) {
    this._entries = entries || requirejs.entries;
  }
  moduleNames() {
    return Object.keys(this._entries);
  }
  has(moduleName) {
    return moduleName in this._entries;
  }
  get(moduleName) {
    return require(moduleName);
  }
}

/**
 * This module defines a subclass of Ember.DefaultResolver that adds two
 * important features:
 *
 *  1) The resolver makes the container aware of es6 modules via the AMD
 *     output. The loader's _moduleEntries is consulted so that classes can be
 *     resolved directly via the module loader, without needing a manual
 *     `import`.
 *  2) is able to provide injections to classes that implement `extend`
 *     (as is typical with Ember).
 */

function parseName(fullName) {
  if (fullName.parsedName === true) { return fullName; }

  let prefix, type, name;
  let fullNameParts = fullName.split('@');

  if (fullNameParts.length === 2) {
    let prefixParts = fullNameParts[0].split(':');

    if (prefixParts.length === 2) {
      if (prefixParts[1].length === 0) {
        type = prefixParts[0];
        name = `@${fullNameParts[1]}`;
      } else {
        prefix = prefixParts[1];
        type = prefixParts[0];
        name = fullNameParts[1];
      }
    } else {
      let nameParts = fullNameParts[1].split(':');

      prefix = fullNameParts[0];
      type = nameParts[0];
      name = nameParts[1];
    }

    if (type === 'template' && prefix.lastIndexOf('components/', 0) === 0) {
      name = `components/${name}`;
      prefix = prefix.slice(11);
    }
  } else {
    fullNameParts = fullName.split(':');
    type = fullNameParts[0];
    name = fullNameParts[1];
  }

  let fullNameWithoutType = name;
  let namespace = get(this, 'namespace');
  let root = namespace;

  return {
    parsedName: true,
    fullName: fullName,
    prefix: prefix || this.prefix({type: type}),
    type: type,
    fullNameWithoutType: fullNameWithoutType,
    name: name,
    root: root,
    resolveMethodName: "resolve" + classify(type)
  };
}

function resolveOther(parsedName) {
  assert('`modulePrefix` must be defined', this.namespace.modulePrefix);

  let normalizedModuleName = this.findModuleName(parsedName);

  if (normalizedModuleName) {
    let defaultExport = this._extractDefaultExport(normalizedModuleName, parsedName);

    if (defaultExport === undefined) {
      throw new Error(` Expected to find: '${parsedName.fullName}' within '${normalizedModuleName}' but got 'undefined'. Did you forget to 'export default' within '${normalizedModuleName}'?`);
    }

    if (this.shouldWrapInClassFactory(defaultExport, parsedName)) {
      defaultExport = classFactory(defaultExport);
    }

    return defaultExport;
  }
}

const Resolver = EmberObject.extend({
  resolveOther,
  parseName,
  pluralizedTypes: null,
  moduleRegistry: null,

  makeToString(factory, fullName) {
    return '' + this.namespace.modulePrefix + '@' + fullName + ':';
  },

  shouldWrapInClassFactory(/* module, parsedName */){
    return false;
  },

  init() {
    this._super();
    this.moduleBasedResolver = true;

    if (!this._moduleRegistry) {
      this._moduleRegistry = new ModuleRegistry();
    }

    this._normalizeCache = Object.create(null);

    this.pluralizedTypes = this.pluralizedTypes || Object.create(null);

    if (!this.pluralizedTypes.config) {
      this.pluralizedTypes.config = 'config';
    }
    this._deprecatedPodModulePrefix = false;
  },

  normalize(fullName) {
    return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this._normalize(fullName));
  },

  resolve(fullName) {
    let parsedName = this.parseName(fullName);
    let resolveMethodName = parsedName.resolveMethodName;
    let resolved;

    if (typeof this[resolveMethodName] === 'function') {
      resolved = this[resolveMethodName](parsedName);
    }

    if (resolved == null) {
      resolved = this.resolveOther(parsedName);
    }

    return resolved;
  },

  _normalize(fullName) {
    // A) Convert underscores to dashes
    // B) Convert camelCase to dash-case, except for components (their
    //    templates) and helpers where we want to avoid shadowing camelCase
    //    expressions
    // C) replace `.` with `/` in order to make nested controllers work in the following cases
    //      1. `needs: ['posts/post']`
    //      2. `{{render "posts/post"}}`
    //      3. `this.render('posts/post')` from Route

    let split = fullName.split(':');
    if (split.length > 1) {
      let type = split[0];

      if (
        type === 'component' ||
        type === 'helper' ||
        (type === 'template' && split[1].indexOf('components/') === 0)
      ) {
        return type + ':' + split[1].replace(/_/g, '-');
      } else {
        return type + ':' + dasherize(split[1].replace(/\./g, '/'));
      }
    } else {
      return fullName;
    }
  },

  pluralize(type) {
    return this.pluralizedTypes[type] || (this.pluralizedTypes[type] = type + 's');
  },

  podBasedLookupWithPrefix(podPrefix, parsedName) {
    let fullNameWithoutType = parsedName.fullNameWithoutType;

    if (parsedName.type === 'template') {
      fullNameWithoutType = fullNameWithoutType.replace(/^components\//, '');
    }

    return podPrefix + '/' + fullNameWithoutType + '/' + parsedName.type;
  },

  podBasedModuleName(parsedName) {
    let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix;

    return this.podBasedLookupWithPrefix(podPrefix, parsedName);
  },

  podBasedComponentsInSubdir(parsedName) {
    let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix;
    podPrefix = podPrefix + '/components';

    if (parsedName.type === 'component' || /^components/.test(parsedName.fullNameWithoutType)) {
      return this.podBasedLookupWithPrefix(podPrefix, parsedName);
    }
  },

  resolveEngine(parsedName) {
    let engineName = parsedName.fullNameWithoutType;
    let engineModule = engineName + '/engine';

    if (this._moduleRegistry.has(engineModule)) {
      return this._extractDefaultExport(engineModule);
    }
  },

  resolveRouteMap(parsedName) {
    let engineName = parsedName.fullNameWithoutType;
    let engineRoutesModule = engineName + '/routes';

    if (this._moduleRegistry.has(engineRoutesModule)) {
      let routeMap = this._extractDefaultExport(engineRoutesModule);

      assert(`The route map for ${engineName} should be wrapped by 'buildRoutes' before exporting.` , routeMap.isRouteMap);

      return routeMap;
    }
  },

  resolveTemplate(parsedName) {
    let resolved = this.resolveOther(parsedName);
    if (resolved == null) {
      resolved = Ember.TEMPLATES[parsedName.fullNameWithoutType];
    }
    return resolved;
  },

  mainModuleName(parsedName) {
    if (parsedName.fullNameWithoutType === 'main') {
      // if router:main or adapter:main look for a module with just the type first
      return parsedName.prefix + '/' + parsedName.type;
    }
  },

  defaultModuleName(parsedName) {
    return parsedName.prefix + '/' +  this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType;
  },

  nestedColocationComponentModuleName(parsedName) {
    if (parsedName.type === 'component') {
      return parsedName.prefix + '/' +  this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType + '/index';
    }
  },

  prefix(parsedName) {
    let tmpPrefix = this.namespace.modulePrefix;

    if (this.namespace[parsedName.type + 'Prefix']) {
      tmpPrefix = this.namespace[parsedName.type + 'Prefix'];
    }

    return tmpPrefix;
  },

  /**

   A listing of functions to test for moduleName's based on the provided
   `parsedName`. This allows easy customization of additional module based
   lookup patterns.

   @property moduleNameLookupPatterns
   @returns {Ember.Array}
   */
  moduleNameLookupPatterns: computed(function(){
    return [
      this.podBasedModuleName,
      this.podBasedComponentsInSubdir,
      this.mainModuleName,
      this.defaultModuleName,
      this.nestedColocationComponentModuleName,
    ];
  }).readOnly(),

  findModuleName(parsedName, loggingDisabled){
    let moduleNameLookupPatterns = this.get('moduleNameLookupPatterns');
    let moduleName;

    for (let index = 0, length = moduleNameLookupPatterns.length; index < length; index++) {
      let item = moduleNameLookupPatterns[index];

      let tmpModuleName = item.call(this, parsedName);

      // allow treat all dashed and all underscored as the same thing
      // supports components with dashes and other stuff with underscores.
      if (tmpModuleName) {
        tmpModuleName = this.chooseModuleName(tmpModuleName, parsedName);
      }

      if (tmpModuleName && this._moduleRegistry.has(tmpModuleName)) {
        moduleName = tmpModuleName;
      }

      if (!loggingDisabled) {
        this._logLookup(moduleName, parsedName, tmpModuleName);
      }

      if (moduleName) {
        return moduleName;
      }
    }
  },

  chooseModuleName(moduleName, parsedName) {
    let underscoredModuleName = underscore(moduleName);

    if (moduleName !== underscoredModuleName && this._moduleRegistry.has(moduleName) && this._moduleRegistry.has(underscoredModuleName)) {
      throw new TypeError(`Ambiguous module names: '${ moduleName}' and '${underscoredModuleName }'`);
    }

    if (this._moduleRegistry.has(moduleName)) {
      return moduleName;
    } else if (this._moduleRegistry.has(underscoredModuleName)) {
      return underscoredModuleName;
    }
    // workaround for dasherized partials:
    // something/something/-something => something/something/_something
    let partializedModuleName = moduleName.replace(/\/-([^/]*)$/, '/_$1');

    if (this._moduleRegistry.has(partializedModuleName)) {
      deprecate('Modules should not contain underscores. ' +
      'Attempted to lookup "'+moduleName+'" which ' +
      'was not found. Please rename "'+partializedModuleName+'" '+
      'to "'+moduleName+'" instead.', false,
      { id: 'ember-resolver.underscored-modules', until: '3.0.0' });

      return partializedModuleName;
    }

    if (DEBUG) {
      let isCamelCaseHelper = parsedName.type === 'helper' && /[a-z]+[A-Z]+/.test(moduleName);
      if (isCamelCaseHelper) {
        this._camelCaseHelperWarnedNames = this._camelCaseHelperWarnedNames || [];
        let alreadyWarned = this._camelCaseHelperWarnedNames.indexOf(parsedName.fullName) > -1;
        if (!alreadyWarned && this._moduleRegistry.has(dasherize(moduleName))) {
          this._camelCaseHelperWarnedNames.push(parsedName.fullName);
          warn('Attempted to lookup "' + parsedName.fullName + '" which ' +
          'was not found. In previous versions of ember-resolver, a bug would have ' +
          'caused the module at "' + dasherize(moduleName) + '" to be ' +
          'returned for this camel case helper name. This has been fixed. ' +
          'Use the dasherized name to resolve the module that would have been ' +
          'returned in previous versions.',
          false,
          { id: 'ember-resolver.camelcase-helper-names', until: '3.0.0' });
        }
      }
    }
  },

  // used by Ember.DefaultResolver.prototype._logLookup
  lookupDescription(fullName) {
    let parsedName = this.parseName(fullName);

    let moduleName = this.findModuleName(parsedName, true);

    return moduleName;
  },

  // only needed until 1.6.0-beta.2 can be required
  _logLookup(found, parsedName, description) {
    if (!Ember.ENV.LOG_MODULE_RESOLVER && !parsedName.root.LOG_RESOLVER) {
      return;
    }

    let padding;
    let symbol = found ? '[✓]' : '[ ]';

    if (parsedName.fullName.length > 60) {
      padding = '.';
    } else {
      padding = new Array(60 - parsedName.fullName.length).join('.');
    }

    if (!description) {
      description = this.lookupDescription(parsedName);
    }

    /* eslint-disable no-console */
    if (console && console.info) {
      console.info(symbol, parsedName.fullName, padding, description);
    }
  },

  knownForType(type) {
    let moduleKeys = this._moduleRegistry.moduleNames();

    let items = Object.create(null);
    for (let index = 0, length = moduleKeys.length; index < length; index++) {
      let moduleName = moduleKeys[index];
      let fullname = this.translateToContainerFullname(type, moduleName);

      if (fullname) {
        items[fullname] = true;
      }
    }

    return items;
  },

  translateToContainerFullname(type, moduleName) {
    let prefix = this.prefix({ type });

    // Note: using string manipulation here rather than regexes for better performance.
    // pod modules
    // '^' + prefix + '/(.+)/' + type + '$'
    let podPrefix = prefix + '/';
    let podSuffix = '/' + type;
    let start = moduleName.indexOf(podPrefix);
    let end = moduleName.indexOf(podSuffix);

    if (start === 0 && end === (moduleName.length - podSuffix.length) &&
        moduleName.length > (podPrefix.length + podSuffix.length)) {
      return type + ':' + moduleName.slice(start + podPrefix.length, end);
    }

    // non-pod modules
    // '^' + prefix + '/' + pluralizedType + '/(.+)$'
    let pluralizedType = this.pluralize(type);
    let nonPodPrefix = prefix + '/' + pluralizedType + '/';

    if (moduleName.indexOf(nonPodPrefix) === 0 && moduleName.length > nonPodPrefix.length) {
      return type + ':' + moduleName.slice(nonPodPrefix.length);
    }
  },

  _extractDefaultExport(normalizedModuleName) {
    let module = require(normalizedModuleName, null, null, true /* force sync */);

    if (module && module['default']) {
      module = module['default'];
    }

    return module;
  }
});

Resolver.reopenClass({
  moduleBasedResolver: true
});

export default Resolver;
<commit_msg>fix: resolve `@scope/package` namespaces<commit_after>/* globals requirejs, require */

import Ember from 'ember';
import { assert, deprecate, warn } from '@ember/debug';
import EmberObject, { get, computed } from '@ember/object';
import { dasherize, classify, underscore } from '@ember/string';
import { DEBUG } from '@glimmer/env';
import classFactory from '../../utils/class-factory';

if (typeof requirejs.entries === 'undefined') {
  requirejs.entries = requirejs._eak_seen;
}

export class ModuleRegistry {
  constructor(entries) {
    this._entries = entries || requirejs.entries;
  }
  moduleNames() {
    return Object.keys(this._entries);
  }
  has(moduleName) {
    return moduleName in this._entries;
  }
  get(moduleName) {
    return require(moduleName);
  }
}

/**
 * This module defines a subclass of Ember.DefaultResolver that adds two
 * important features:
 *
 *  1) The resolver makes the container aware of es6 modules via the AMD
 *     output. The loader's _moduleEntries is consulted so that classes can be
 *     resolved directly via the module loader, without needing a manual
 *     `import`.
 *  2) is able to provide injections to classes that implement `extend`
 *     (as is typical with Ember).
 */

function parseName(fullName) {
  if (fullName.parsedName === true) { return fullName; }

  let prefix, type, name;
  let fullNameParts = fullName.split('@');

  if (fullNameParts.length === 3) {
    if (fullNameParts[0].length === 0) {
      // leading scoped namespace: `@scope/pkg@type:name`
      prefix = `@${fullNameParts[1]}`;
      let prefixParts = fullNameParts[2].split(':');
      type = prefixParts[0];
      name = prefixParts[1];
    } else {
      // interweaved scoped namespace: `type:@scope/pkg@name`
      prefix = `@${fullNameParts[1]}`;
      type = fullNameParts[0].slice(0, -1);
      name = fullNameParts[2];
    }

    if (type === 'template:components') {
      name = `components/${name}`;
      type = 'template';
    }
  } else if (fullNameParts.length === 2) {
    let prefixParts = fullNameParts[0].split(':');

    if (prefixParts.length === 2) {
      if (prefixParts[1].length === 0) {
        type = prefixParts[0];
        name = `@${fullNameParts[1]}`;
      } else {
        prefix = prefixParts[1];
        type = prefixParts[0];
        name = fullNameParts[1];
      }
    } else {
      let nameParts = fullNameParts[1].split(':');

      prefix = fullNameParts[0];
      type = nameParts[0];
      name = nameParts[1];
    }

    if (type === 'template' && prefix.lastIndexOf('components/', 0) === 0) {
      name = `components/${name}`;
      prefix = prefix.slice(11);
    }
  } else {
    fullNameParts = fullName.split(':');
    type = fullNameParts[0];
    name = fullNameParts[1];
  }

  let fullNameWithoutType = name;
  let namespace = get(this, 'namespace');
  let root = namespace;

  return {
    parsedName: true,
    fullName: fullName,
    prefix: prefix || this.prefix({type: type}),
    type: type,
    fullNameWithoutType: fullNameWithoutType,
    name: name,
    root: root,
    resolveMethodName: "resolve" + classify(type)
  };
}

function resolveOther(parsedName) {
  assert('`modulePrefix` must be defined', this.namespace.modulePrefix);

  let normalizedModuleName = this.findModuleName(parsedName);

  if (normalizedModuleName) {
    let defaultExport = this._extractDefaultExport(normalizedModuleName, parsedName);

    if (defaultExport === undefined) {
      throw new Error(` Expected to find: '${parsedName.fullName}' within '${normalizedModuleName}' but got 'undefined'. Did you forget to 'export default' within '${normalizedModuleName}'?`);
    }

    if (this.shouldWrapInClassFactory(defaultExport, parsedName)) {
      defaultExport = classFactory(defaultExport);
    }

    return defaultExport;
  }
}

const Resolver = EmberObject.extend({
  resolveOther,
  parseName,
  pluralizedTypes: null,
  moduleRegistry: null,

  makeToString(factory, fullName) {
    return '' + this.namespace.modulePrefix + '@' + fullName + ':';
  },

  shouldWrapInClassFactory(/* module, parsedName */){
    return false;
  },

  init() {
    this._super();
    this.moduleBasedResolver = true;

    if (!this._moduleRegistry) {
      this._moduleRegistry = new ModuleRegistry();
    }

    this._normalizeCache = Object.create(null);

    this.pluralizedTypes = this.pluralizedTypes || Object.create(null);

    if (!this.pluralizedTypes.config) {
      this.pluralizedTypes.config = 'config';
    }
    this._deprecatedPodModulePrefix = false;
  },

  normalize(fullName) {
    return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this._normalize(fullName));
  },

  resolve(fullName) {
    let parsedName = this.parseName(fullName);
    let resolveMethodName = parsedName.resolveMethodName;
    let resolved;

    if (typeof this[resolveMethodName] === 'function') {
      resolved = this[resolveMethodName](parsedName);
    }

    if (resolved == null) {
      resolved = this.resolveOther(parsedName);
    }

    return resolved;
  },

  _normalize(fullName) {
    // A) Convert underscores to dashes
    // B) Convert camelCase to dash-case, except for components (their
    //    templates) and helpers where we want to avoid shadowing camelCase
    //    expressions
    // C) replace `.` with `/` in order to make nested controllers work in the following cases
    //      1. `needs: ['posts/post']`
    //      2. `{{render "posts/post"}}`
    //      3. `this.render('posts/post')` from Route

    let split = fullName.split(':');
    if (split.length > 1) {
      let type = split[0];

      if (
        type === 'component' ||
        type === 'helper' ||
        (type === 'template' && split[1].indexOf('components/') === 0)
      ) {
        return type + ':' + split[1].replace(/_/g, '-');
      } else {
        return type + ':' + dasherize(split[1].replace(/\./g, '/'));
      }
    } else {
      return fullName;
    }
  },

  pluralize(type) {
    return this.pluralizedTypes[type] || (this.pluralizedTypes[type] = type + 's');
  },

  podBasedLookupWithPrefix(podPrefix, parsedName) {
    let fullNameWithoutType = parsedName.fullNameWithoutType;

    if (parsedName.type === 'template') {
      fullNameWithoutType = fullNameWithoutType.replace(/^components\//, '');
    }

    return podPrefix + '/' + fullNameWithoutType + '/' + parsedName.type;
  },

  podBasedModuleName(parsedName) {
    let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix;

    return this.podBasedLookupWithPrefix(podPrefix, parsedName);
  },

  podBasedComponentsInSubdir(parsedName) {
    let podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix;
    podPrefix = podPrefix + '/components';

    if (parsedName.type === 'component' || /^components/.test(parsedName.fullNameWithoutType)) {
      return this.podBasedLookupWithPrefix(podPrefix, parsedName);
    }
  },

  resolveEngine(parsedName) {
    let engineName = parsedName.fullNameWithoutType;
    let engineModule = engineName + '/engine';

    if (this._moduleRegistry.has(engineModule)) {
      return this._extractDefaultExport(engineModule);
    }
  },

  resolveRouteMap(parsedName) {
    let engineName = parsedName.fullNameWithoutType;
    let engineRoutesModule = engineName + '/routes';

    if (this._moduleRegistry.has(engineRoutesModule)) {
      let routeMap = this._extractDefaultExport(engineRoutesModule);

      assert(`The route map for ${engineName} should be wrapped by 'buildRoutes' before exporting.` , routeMap.isRouteMap);

      return routeMap;
    }
  },

  resolveTemplate(parsedName) {
    let resolved = this.resolveOther(parsedName);
    if (resolved == null) {
      resolved = Ember.TEMPLATES[parsedName.fullNameWithoutType];
    }
    return resolved;
  },

  mainModuleName(parsedName) {
    if (parsedName.fullNameWithoutType === 'main') {
      // if router:main or adapter:main look for a module with just the type first
      return parsedName.prefix + '/' + parsedName.type;
    }
  },

  defaultModuleName(parsedName) {
    return parsedName.prefix + '/' +  this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType;
  },

  nestedColocationComponentModuleName(parsedName) {
    if (parsedName.type === 'component') {
      return parsedName.prefix + '/' +  this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType + '/index';
    }
  },

  prefix(parsedName) {
    let tmpPrefix = this.namespace.modulePrefix;

    if (this.namespace[parsedName.type + 'Prefix']) {
      tmpPrefix = this.namespace[parsedName.type + 'Prefix'];
    }

    return tmpPrefix;
  },

  /**

   A listing of functions to test for moduleName's based on the provided
   `parsedName`. This allows easy customization of additional module based
   lookup patterns.

   @property moduleNameLookupPatterns
   @returns {Ember.Array}
   */
  moduleNameLookupPatterns: computed(function(){
    return [
      this.podBasedModuleName,
      this.podBasedComponentsInSubdir,
      this.mainModuleName,
      this.defaultModuleName,
      this.nestedColocationComponentModuleName,
    ];
  }).readOnly(),

  findModuleName(parsedName, loggingDisabled){
    let moduleNameLookupPatterns = this.get('moduleNameLookupPatterns');
    let moduleName;

    for (let index = 0, length = moduleNameLookupPatterns.length; index < length; index++) {
      let item = moduleNameLookupPatterns[index];

      let tmpModuleName = item.call(this, parsedName);

      // allow treat all dashed and all underscored as the same thing
      // supports components with dashes and other stuff with underscores.
      if (tmpModuleName) {
        tmpModuleName = this.chooseModuleName(tmpModuleName, parsedName);
      }

      if (tmpModuleName && this._moduleRegistry.has(tmpModuleName)) {
        moduleName = tmpModuleName;
      }

      if (!loggingDisabled) {
        this._logLookup(moduleName, parsedName, tmpModuleName);
      }

      if (moduleName) {
        return moduleName;
      }
    }
  },

  chooseModuleName(moduleName, parsedName) {
    let underscoredModuleName = underscore(moduleName);

    if (moduleName !== underscoredModuleName && this._moduleRegistry.has(moduleName) && this._moduleRegistry.has(underscoredModuleName)) {
      throw new TypeError(`Ambiguous module names: '${ moduleName}' and '${underscoredModuleName }'`);
    }

    if (this._moduleRegistry.has(moduleName)) {
      return moduleName;
    } else if (this._moduleRegistry.has(underscoredModuleName)) {
      return underscoredModuleName;
    }
    // workaround for dasherized partials:
    // something/something/-something => something/something/_something
    let partializedModuleName = moduleName.replace(/\/-([^/]*)$/, '/_$1');

    if (this._moduleRegistry.has(partializedModuleName)) {
      deprecate('Modules should not contain underscores. ' +
      'Attempted to lookup "'+moduleName+'" which ' +
      'was not found. Please rename "'+partializedModuleName+'" '+
      'to "'+moduleName+'" instead.', false,
      { id: 'ember-resolver.underscored-modules', until: '3.0.0' });

      return partializedModuleName;
    }

    if (DEBUG) {
      let isCamelCaseHelper = parsedName.type === 'helper' && /[a-z]+[A-Z]+/.test(moduleName);
      if (isCamelCaseHelper) {
        this._camelCaseHelperWarnedNames = this._camelCaseHelperWarnedNames || [];
        let alreadyWarned = this._camelCaseHelperWarnedNames.indexOf(parsedName.fullName) > -1;
        if (!alreadyWarned && this._moduleRegistry.has(dasherize(moduleName))) {
          this._camelCaseHelperWarnedNames.push(parsedName.fullName);
          warn('Attempted to lookup "' + parsedName.fullName + '" which ' +
          'was not found. In previous versions of ember-resolver, a bug would have ' +
          'caused the module at "' + dasherize(moduleName) + '" to be ' +
          'returned for this camel case helper name. This has been fixed. ' +
          'Use the dasherized name to resolve the module that would have been ' +
          'returned in previous versions.',
          false,
          { id: 'ember-resolver.camelcase-helper-names', until: '3.0.0' });
        }
      }
    }
  },

  // used by Ember.DefaultResolver.prototype._logLookup
  lookupDescription(fullName) {
    let parsedName = this.parseName(fullName);

    let moduleName = this.findModuleName(parsedName, true);

    return moduleName;
  },

  // only needed until 1.6.0-beta.2 can be required
  _logLookup(found, parsedName, description) {
    if (!Ember.ENV.LOG_MODULE_RESOLVER && !parsedName.root.LOG_RESOLVER) {
      return;
    }

    let padding;
    let symbol = found ? '[✓]' : '[ ]';

    if (parsedName.fullName.length > 60) {
      padding = '.';
    } else {
      padding = new Array(60 - parsedName.fullName.length).join('.');
    }

    if (!description) {
      description = this.lookupDescription(parsedName);
    }

    /* eslint-disable no-console */
    if (console && console.info) {
      console.info(symbol, parsedName.fullName, padding, description);
    }
  },

  knownForType(type) {
    let moduleKeys = this._moduleRegistry.moduleNames();

    let items = Object.create(null);
    for (let index = 0, length = moduleKeys.length; index < length; index++) {
      let moduleName = moduleKeys[index];
      let fullname = this.translateToContainerFullname(type, moduleName);

      if (fullname) {
        items[fullname] = true;
      }
    }

    return items;
  },

  translateToContainerFullname(type, moduleName) {
    let prefix = this.prefix({ type });

    // Note: using string manipulation here rather than regexes for better performance.
    // pod modules
    // '^' + prefix + '/(.+)/' + type + '$'
    let podPrefix = prefix + '/';
    let podSuffix = '/' + type;
    let start = moduleName.indexOf(podPrefix);
    let end = moduleName.indexOf(podSuffix);

    if (start === 0 && end === (moduleName.length - podSuffix.length) &&
        moduleName.length > (podPrefix.length + podSuffix.length)) {
      return type + ':' + moduleName.slice(start + podPrefix.length, end);
    }

    // non-pod modules
    // '^' + prefix + '/' + pluralizedType + '/(.+)$'
    let pluralizedType = this.pluralize(type);
    let nonPodPrefix = prefix + '/' + pluralizedType + '/';

    if (moduleName.indexOf(nonPodPrefix) === 0 && moduleName.length > nonPodPrefix.length) {
      return type + ':' + moduleName.slice(nonPodPrefix.length);
    }
  },

  _extractDefaultExport(normalizedModuleName) {
    let module = require(normalizedModuleName, null, null, true /* force sync */);

    if (module && module['default']) {
      module = module['default'];
    }

    return module;
  }
});

Resolver.reopenClass({
  moduleBasedResolver: true
});

export default Resolver;
<|endoftext|>


<commit_before>var redis = require("redis");
var redisHost = process.env.REDIS_HOST;
var redisPass = process.env.REDIS_PASS;

if (!redisPass) throw "Need a password in environmental variables!";

/*
    TODO: Check to make sure this is fine
*/
var client = redis.createClient(6379, redisHost, { auth_pass: redisPass });
client.on("monitor", function (time, args, raw_reply) {
    console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
});

client.on('error', function (error) {
    console.log(error);
});

module.exports = client;<commit_msg>add redisHost backup<commit_after>var redis = require("redis");
var redisHost = process.env.REDIS_HOST;
var redisPass = process.env.REDIS_PASS;

if (!redisHost) redisHost = process.env.REDIS_PORT_6379_TCP_ADDR
if (!redisPass) throw "Need a password in environmental variables!";

/*
    TODO: Check to make sure this is fine
*/
var client = redis.createClient(6379, redisHost, { auth_pass: redisPass });
client.on("monitor", function (time, args, raw_reply) {
    console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
});

client.on('error', function (error) {
    console.log(error);
});

module.exports = client;
<|endoftext|>


<commit_before>// Globals
var angular = angular;
var nOrg = nOrg;
angular.module('nOrg', ['ui.bootstrap', 'ui.keypress'])

  .controller('NOrgCtrl', function NOrgCtrl($scope, $http, $log) {
    $scope.controlName = 'NOrgCtrl';

    $scope.keydown = {
      'tab': 'node.toggle($event)',
      'shift-tab': 'node.toggleProperties($event)', // h

      'down': 'node.cursorDown($event)', // j, s
      'up': 'node.cursorUp($event)',     // k, w
      'right': 'node.cursorRight($event)',  // d
      'left': 'node.cursorLeft($event)',    // a

      'shift-down': 'node.applyCursor("moveDown", $event)',
      'shift-up': 'node.applyCursor("moveUp", $event)',
      'shift-right': 'node.applyCursor("demote", $event)',
      'shift-left': 'node.applyCursor("promote", $event)',

      'shift-enter': 'shiftEnter($event)'
    };

    $http.get('../nOrg-nodes.json').success(function loadNode(node) {
      // Load the initial nodes JSON
      $scope.node = nOrg.newRoot(node);
    });

    $scope.newProperty = function newProperty($event) {
      this.node.$cursorObject.$newProperty(this.property);
      this.property = '';
    };

    $scope.shiftEnter = function shiftEnter($event) {
      if (this.node.$cursorIndex !== undefined) {
        $event.target.parentElement.parentElement.parentElement
          .lastElementChild.firstElementChild.lastElementChild.focus();
      } else {
        this.node.$cursorObject.newSibling();
      }
    };
  })

  .directive('norgFocus', function norgFocus() {
    return function (scope, element, attrs) {
      attrs.$observe('norgFocus', function (newValue) {
        if (newValue === 'true') {
          element[0].focus();
        }
      });
    };
  });

//NOrgCtrl.$inject = ['$scope', '$http'];
<commit_msg>Remove comments for deleted keymap aliases<commit_after>// Globals
var angular = angular;
var nOrg = nOrg;
angular.module('nOrg', ['ui.bootstrap', 'ui.keypress'])

  .controller('NOrgCtrl', function NOrgCtrl($scope, $http, $log) {
    $scope.controlName = 'NOrgCtrl';

    $scope.keydown = {
      'tab': 'node.toggle($event)',
      'shift-tab': 'node.toggleProperties($event)',

      'down': 'node.cursorDown($event)',
      'up': 'node.cursorUp($event)',
      'right': 'node.cursorRight($event)',
      'left': 'node.cursorLeft($event)',

      'shift-down': 'node.applyCursor("moveDown", $event)',
      'shift-up': 'node.applyCursor("moveUp", $event)',
      'shift-right': 'node.applyCursor("demote", $event)',
      'shift-left': 'node.applyCursor("promote", $event)',

      'shift-enter': 'shiftEnter($event)'
    };

    $http.get('../nOrg-nodes.json').success(function loadNode(node) {
      // Load the initial nodes JSON
      $scope.node = nOrg.newRoot(node);
    });

    $scope.newProperty = function newProperty($event) {
      this.node.$cursorObject.$newProperty(this.property);
      this.property = '';
    };

    $scope.shiftEnter = function shiftEnter($event) {
      if (this.node.$cursorIndex !== undefined) {
        $event.target.parentElement.parentElement.parentElement
          .lastElementChild.firstElementChild.lastElementChild.focus();
      } else {
        this.node.$cursorObject.newSibling();
      }
    };
  })

  .directive('norgFocus', function norgFocus() {
    return function (scope, element, attrs) {
      attrs.$observe('norgFocus', function (newValue) {
        if (newValue === 'true') {
          element[0].focus();
        }
      });
    };
  });

//NOrgCtrl.$inject = ['$scope', '$http'];
<|endoftext|>


<commit_before>'use strict';

const { get } = require('@terascope/utils');
const { isFatalError } = require('@terascope/job-components');
const { ExecutionController, formatURL } = require('@terascope/teraslice-messaging');
const { makeStateStore, makeAnalyticsStore } = require('../../cluster/storage');
const { waitForWorkerShutdown } = require('../helpers/worker-shutdown');
const { generateWorkerId, makeLogger } = require('../helpers/terafoundation');
const Slice = require('./slice');

class Worker {
    constructor(context, executionContext) {
        const workerId = generateWorkerId(context);
        const logger = makeLogger(context, executionContext, 'worker');
        const events = context.apis.foundation.getSystemEvents();

        const {
            slicer_port: slicerPort,
            slicer_hostname: slicerHostname,
        } = executionContext.config;

        const config = context.sysconfig.teraslice;
        const networkLatencyBuffer = get(config, 'network_latency_buffer');
        const actionTimeout = get(config, 'action_timeout');
        const workerDisconnectTimeout = get(config, 'worker_disconnect_timeout');
        const shutdownTimeout = get(config, 'shutdown_timeout');

        this.client = new ExecutionController.Client({
            executionControllerUrl: formatURL(slicerHostname, slicerPort),
            workerId,
            networkLatencyBuffer,
            connectTimeout: workerDisconnectTimeout,
            actionTimeout,
            logger,
        });

        this.slice = new Slice(context, executionContext);

        this.stores = {};
        this.executionContext = executionContext;
        this.shutdownTimeout = shutdownTimeout;
        this.context = context;
        this.workerId = workerId;
        this.logger = logger;
        this.events = events;

        this.isShuttingDown = false;
        this.isProcessing = false;
        this.isInitialized = false;
        this.shouldShutdown = false;
        this.forceShutdown = false;
        this.slicesProcessed = 0;
    }

    async initialize() {
        const { context } = this;
        this.isInitialized = true;

        await this.executionContext.initialize();

        const stateStore = makeStateStore(context);
        const analyticsStore = makeAnalyticsStore(context);
        this.stores.stateStore = await stateStore;
        this.stores.analyticsStore = await analyticsStore;

        this.client.onServerShutdown(() => {
            this.logger.warn('Execution Controller shutdown, exiting...');
            this.shouldShutdown = true;
        });

        await this.client.start();
    }

    async run() {
        let running = false;

        const _run = async () => {
            running = true;

            try {
                await this.runOnce();
            } catch (err) {
                this.logger.fatal(err, 'Worker must shutdown to Fatal Error');
                this.shutdown(false);
            } finally {
                running = false;
            }
        };

        await new Promise((resolve) => {
            const interval = setInterval(() => {
                if (this.forceShutdown) {
                    done();
                    return;
                }

                if (running) return;

                if (this.isShuttingDown || this.shouldShutdown) {
                    done();
                    return;
                }

                _run();
            }, 5);

            function done() {
                clearInterval(interval);
                resolve();
            }
        });
    }

    async runOnce() {
        if (this.isShuttingDown || this.forceShutdown || this.shouldShutdown) return;

        this.logger.trace('waiting for new slice from execution controller');
        const msg = await this.client.waitForSlice(() => this.isShuttingDown);

        if (!msg) {
            this.logger.debug(`${this.workerId} worker is idle`);
            return;
        }

        this.isProcessing = true;

        const { exId } = this.executionContext;

        try {
            await this.slice.initialize(msg, this.stores);

            await this.slice.run();

            const { slice_id: sliceId } = this.slice.slice;
            this.logger.info(`slice complete for execution ${exId}`);

            await this.client.sendSliceComplete({
                slice: this.slice.slice,
                analytics: this.slice.analyticsData,
            });

            await this.executionContext.onSliceFinished(sliceId);
        } catch (err) {
            this.logger.error(err, `slice run error for execution ${exId}`);

            if (isFatalError(err)) {
                throw err;
            }

            await this.client.sendSliceComplete({
                slice: this.slice.slice,
                analytics: this.slice.analyticsData,
                error: err.toString(),
            });
        }

        this.isProcessing = false;
        this.slicesProcessed += 1;
    }

    async shutdown(block = true) {
        if (this.isShutdown) return;
        if (!this.isInitialized) return;
        if (this.isShuttingDown) {
            const msgs = [
                'worker',
                `shutdown was called for ${this.exId}`,
                'but it was already shutting down',
                block ? ', will block until done' : '',
            ];
            this.logger.debug(msgs.join(' '));

            if (block) {
                await waitForWorkerShutdown(this.context, 'worker:shutdown:complete');
            }
            return;
        }

        const { exId } = this.executionContext;

        this.client.available = false;
        this.isShuttingDown = true;

        const shutdownErrs = [];
        const pushError = (err) => {
            shutdownErrs.push(err);
        };

        this.logger.warn(`worker shutdown was called for execution ${exId}`);

        // attempt to flush the slice
        // and wait for the slice to finish
        await Promise.all([
            this.slice.flush().catch(pushError),
            this._waitForSliceToFinish().catch(pushError),
        ]);

        this.events.emit('worker:shutdown');
        await this.executionContext.shutdown();

        // make sure ->run() resolves the promise
        this.forceShutdown = true;

        await Promise.all([
            (async () => {
                const stores = Object.values(this.stores);
                await Promise.all(stores.map(store => store.shutdown(true).catch(pushError)));
            })(),
            (async () => {
                await this.slice.shutdown().catch(pushError);
            })(),
            (async () => {
                await this.client.shutdown().catch(pushError);
            })(),
        ]);

        const n = this.slicesProcessed;
        this.logger.warn(
            `worker ${this.workerId} is shutdown for execution ${exId}, processed ${n} slices`
        );
        this.isShutdown = true;

        if (shutdownErrs.length) {
            const errMsg = shutdownErrs.map(e => e.stack).join(', and');
            const shutdownErr = new Error(`Failed to shutdown correctly: ${errMsg}`);
            this.events.emit(this.context, 'worker:shutdown:complete', shutdownErr);
            throw shutdownErr;
        }

        this.events.emit(this.context, 'worker:shutdown:complete');
    }

    _waitForSliceToFinish() {
        if (!this.isProcessing) return Promise.resolve();

        const { logger } = this;
        const startTime = Date.now();

        return new Promise((resolve, reject) => {
            let timeout;
            let interval;
            const done = (err) => {
                clearInterval(interval);
                clearTimeout(timeout);
                if (err) {
                    reject(err);
                    return;
                }
                resolve();
            };

            interval = setInterval(() => {
                const elapsed = (Date.now() - startTime) / 1000;
                if (!this.isProcessing) {
                    logger.trace(
                        `is done with current slice, shutdown counter took ${elapsed} seconds`
                    );
                    done();
                    return;
                }

                /* istanbul ignore if */
                if (elapsed % 60 === 0) {
                    logger.info(
                        `shutdown sequence initiated, but is still processing. Will force shutdown in ${elapsed} seconds`
                    );
                }
            }, 100);

            timeout = setTimeout(() => {
                const seconds = this.shutdownTimeout / 1000;
                const err = new Error(
                    `Worker shutdown timeout after ${seconds} seconds, forcing shutdown`
                );
                done(err);
            }, this.shutdownTimeout);
        });
    }
}

module.exports = Worker;
<commit_msg>Return full stack for worker error<commit_after>'use strict';

const { get, getFullErrorStack, isFatalError } = require('@terascope/utils');
const { ExecutionController, formatURL } = require('@terascope/teraslice-messaging');
const { makeStateStore, makeAnalyticsStore } = require('../../cluster/storage');
const { waitForWorkerShutdown } = require('../helpers/worker-shutdown');
const { generateWorkerId, makeLogger } = require('../helpers/terafoundation');
const Slice = require('./slice');

class Worker {
    constructor(context, executionContext) {
        const workerId = generateWorkerId(context);
        const logger = makeLogger(context, executionContext, 'worker');
        const events = context.apis.foundation.getSystemEvents();

        const {
            slicer_port: slicerPort,
            slicer_hostname: slicerHostname
        } = executionContext.config;

        const config = context.sysconfig.teraslice;
        const networkLatencyBuffer = get(config, 'network_latency_buffer');
        const actionTimeout = get(config, 'action_timeout');
        const workerDisconnectTimeout = get(config, 'worker_disconnect_timeout');
        const shutdownTimeout = get(config, 'shutdown_timeout');

        this.client = new ExecutionController.Client({
            executionControllerUrl: formatURL(slicerHostname, slicerPort),
            workerId,
            networkLatencyBuffer,
            connectTimeout: workerDisconnectTimeout,
            actionTimeout,
            logger
        });

        this.slice = new Slice(context, executionContext);

        this.stores = {};
        this.executionContext = executionContext;
        this.shutdownTimeout = shutdownTimeout;
        this.context = context;
        this.workerId = workerId;
        this.logger = logger;
        this.events = events;

        this.isShuttingDown = false;
        this.isProcessing = false;
        this.isInitialized = false;
        this.shouldShutdown = false;
        this.forceShutdown = false;
        this.slicesProcessed = 0;
    }

    async initialize() {
        const { context } = this;
        this.isInitialized = true;

        await this.executionContext.initialize();

        const stateStore = makeStateStore(context);
        const analyticsStore = makeAnalyticsStore(context);
        this.stores.stateStore = await stateStore;
        this.stores.analyticsStore = await analyticsStore;

        this.client.onServerShutdown(() => {
            this.logger.warn('Execution Controller shutdown, exiting...');
            this.shouldShutdown = true;
        });

        await this.client.start();
    }

    async run() {
        let running = false;

        const _run = async () => {
            running = true;

            try {
                await this.runOnce();
            } catch (err) {
                this.logger.fatal(err, 'Worker must shutdown to Fatal Error');
                this.shutdown(false);
            } finally {
                running = false;
            }
        };

        await new Promise((resolve) => {
            const interval = setInterval(() => {
                if (this.forceShutdown) {
                    done();
                    return;
                }

                if (running) return;

                if (this.isShuttingDown || this.shouldShutdown) {
                    done();
                    return;
                }

                _run();
            }, 5);

            function done() {
                clearInterval(interval);
                resolve();
            }
        });
    }

    async runOnce() {
        if (this.isShuttingDown || this.forceShutdown || this.shouldShutdown) return;

        this.logger.trace('waiting for new slice from execution controller');
        const msg = await this.client.waitForSlice(() => this.isShuttingDown);

        if (!msg) {
            this.logger.debug(`${this.workerId} worker is idle`);
            return;
        }

        this.isProcessing = true;

        const { exId } = this.executionContext;

        try {
            await this.slice.initialize(msg, this.stores);

            await this.slice.run();

            const { slice_id: sliceId } = this.slice.slice;
            this.logger.info(`slice complete for execution ${exId}`);

            await this.client.sendSliceComplete({
                slice: this.slice.slice,
                analytics: this.slice.analyticsData
            });

            await this.executionContext.onSliceFinished(sliceId);
        } catch (err) {
            this.logger.error(err, `slice run error for execution ${exId}`);

            if (isFatalError(err)) {
                throw err;
            }

            await this.client.sendSliceComplete({
                slice: this.slice.slice,
                analytics: this.slice.analyticsData,
                error: getFullErrorStack(err)
            });
        }

        this.isProcessing = false;
        this.slicesProcessed += 1;
    }

    async shutdown(block = true) {
        if (this.isShutdown) return;
        if (!this.isInitialized) return;
        if (this.isShuttingDown) {
            const msgs = [
                'worker',
                `shutdown was called for ${this.exId}`,
                'but it was already shutting down',
                block ? ', will block until done' : ''
            ];
            this.logger.debug(msgs.join(' '));

            if (block) {
                await waitForWorkerShutdown(this.context, 'worker:shutdown:complete');
            }
            return;
        }

        const { exId } = this.executionContext;

        this.client.available = false;
        this.isShuttingDown = true;

        const shutdownErrs = [];
        const pushError = (err) => {
            shutdownErrs.push(err);
        };

        this.logger.warn(`worker shutdown was called for execution ${exId}`);

        // attempt to flush the slice
        // and wait for the slice to finish
        await Promise.all([
            this.slice.flush().catch(pushError),
            this._waitForSliceToFinish().catch(pushError)
        ]);

        this.events.emit('worker:shutdown');
        await this.executionContext.shutdown();

        // make sure ->run() resolves the promise
        this.forceShutdown = true;

        await Promise.all([
            (async () => {
                const stores = Object.values(this.stores);
                await Promise.all(stores.map(store => store.shutdown(true).catch(pushError)));
            })(),
            (async () => {
                await this.slice.shutdown().catch(pushError);
            })(),
            (async () => {
                await this.client.shutdown().catch(pushError);
            })()
        ]);

        const n = this.slicesProcessed;
        this.logger.warn(
            `worker ${this.workerId} is shutdown for execution ${exId}, processed ${n} slices`
        );
        this.isShutdown = true;

        if (shutdownErrs.length) {
            const errMsg = shutdownErrs.map(e => e.stack).join(', and');
            const shutdownErr = new Error(`Failed to shutdown correctly: ${errMsg}`);
            this.events.emit(this.context, 'worker:shutdown:complete', shutdownErr);
            throw shutdownErr;
        }

        this.events.emit(this.context, 'worker:shutdown:complete');
    }

    _waitForSliceToFinish() {
        if (!this.isProcessing) return Promise.resolve();

        const { logger } = this;
        const startTime = Date.now();

        return new Promise((resolve, reject) => {
            let timeout;
            let interval;
            const done = (err) => {
                clearInterval(interval);
                clearTimeout(timeout);
                if (err) {
                    reject(err);
                    return;
                }
                resolve();
            };

            interval = setInterval(() => {
                const elapsed = (Date.now() - startTime) / 1000;
                if (!this.isProcessing) {
                    logger.trace(
                        `is done with current slice, shutdown counter took ${elapsed} seconds`
                    );
                    done();
                    return;
                }

                /* istanbul ignore if */
                if (elapsed % 60 === 0) {
                    logger.info(
                        `shutdown sequence initiated, but is still processing. Will force shutdown in ${elapsed} seconds`
                    );
                }
            }, 100);

            timeout = setTimeout(() => {
                const seconds = this.shutdownTimeout / 1000;
                const err = new Error(
                    `Worker shutdown timeout after ${seconds} seconds, forcing shutdown`
                );
                done(err);
            }, this.shutdownTimeout);
        });
    }
}

module.exports = Worker;
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {FormattedMessage, injectIntl} from 'react-intl'

import ButtonGroup from '../ButtonGroup'
import Typography from '../Typography'
import {StyledPagination, StyledPaginationButton} from './StyledComponents'

/**
 * Controlled Pagination component
 */
const Pagination = ({totalCount, recordsPerPage, currentPage, onPageChange, intl}) => {
  const totalPages = Math.ceil(totalCount / recordsPerPage)
  const start = Math.min((currentPage - 1) * recordsPerPage + 1, totalCount)
  const to = Math.min(currentPage * recordsPerPage, totalCount)

  const msg = id => intl.formatMessage({id})

  return (
    <StyledPagination>
       <ButtonGroup>
        <StyledPaginationButton
          disabled={currentPage === 1}
          label={msg('client.component.pagination.firstPageTitle')}
          iconOnly
          icon="chevron-double-left"
          onClick={() => onPageChange(1)}/>
        <StyledPaginationButton
          disabled={currentPage === 1}
          label={msg('client.component.pagination.prePageTitle')}
          iconOnly
          icon="chevron-left"
          onClick={() => onPageChange(currentPage - 1)}/>
        <StyledPaginationButton
          disabled={currentPage >= totalPages}
          label={msg('client.component.pagination.nextPageTitle')}
          iconOnly
          icon="chevron-right"
          onClick={() => onPageChange(currentPage + 1)}/>
        <StyledPaginationButton
          disabled={currentPage >= totalPages}
          label={msg('client.component.pagination.lastPageTitle')}
          iconOnly
          icon="chevron-double-right"
          onClick={() => onPageChange(totalPages)}/>
      </ButtonGroup>

      {totalCount > 0 && (
        <Typography.Span>
          <FormattedMessage id="client.component.pagination.text" values={{
            start,
            to,
            total: totalCount
          }}/>
      </Typography.Span>)}
    </StyledPagination>
  )
}

Pagination.propTypes = {
  intl: PropTypes.object.isRequired,
  /**
   * Currently displayed page
   */
  currentPage: PropTypes.number.isRequired,
  /**
   * Total of records available
   */
  totalCount: PropTypes.number.isRequired,
  /**
   * Limit for a page
   */
  recordsPerPage: PropTypes.number.isRequired,
  /**
   * Callback on page change with provided button, returns new page as single argument
   */
  onPageChange: PropTypes.func.isRequired
}

export default injectIntl(Pagination)
<commit_msg>fix(tocco-ui): fix pagination prop types<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {FormattedMessage, injectIntl} from 'react-intl'

import ButtonGroup from '../ButtonGroup'
import Typography from '../Typography'
import {StyledPagination, StyledPaginationButton} from './StyledComponents'

/**
 * Controlled Pagination component
 */
const Pagination = ({totalCount, recordsPerPage, currentPage, onPageChange, intl}) => {
  const totalPages = Math.ceil(totalCount / recordsPerPage)
  const start = Math.min((currentPage - 1) * recordsPerPage + 1, totalCount)
  const to = Math.min(currentPage * recordsPerPage, totalCount)

  const msg = id => intl.formatMessage({id})

  return (
    <StyledPagination>
       <ButtonGroup>
        <StyledPaginationButton
          disabled={currentPage === 1}
          label={msg('client.component.pagination.firstPageTitle')}
          iconOnly
          icon="chevron-double-left"
          onClick={() => onPageChange(1)}/>
        <StyledPaginationButton
          disabled={currentPage === 1}
          label={msg('client.component.pagination.prePageTitle')}
          iconOnly
          icon="chevron-left"
          onClick={() => onPageChange(currentPage - 1)}/>
        <StyledPaginationButton
          disabled={currentPage >= totalPages}
          label={msg('client.component.pagination.nextPageTitle')}
          iconOnly
          icon="chevron-right"
          onClick={() => onPageChange(currentPage + 1)}/>
        <StyledPaginationButton
          disabled={currentPage >= totalPages}
          label={msg('client.component.pagination.lastPageTitle')}
          iconOnly
          icon="chevron-double-right"
          onClick={() => onPageChange(totalPages)}/>
      </ButtonGroup>

      {totalCount > 0 && (
        <Typography.Span>
          <FormattedMessage id="client.component.pagination.text" values={{
            start,
            to,
            total: totalCount
          }}/>
      </Typography.Span>)}
    </StyledPagination>
  )
}

Pagination.propTypes = {
  intl: PropTypes.object.isRequired,
  /**
   * Currently displayed page
   */
  currentPage: PropTypes.number.isRequired,
  /**
   * Total of records available
   */
  totalCount: PropTypes.number,
  /**
   * Limit for a page
   */
  recordsPerPage: PropTypes.number.isRequired,
  /**
   * Callback on page change with provided button, returns new page as single argument
   */
  onPageChange: PropTypes.func.isRequired
}

export default injectIntl(Pagination)
<|endoftext|>


<commit_before>import Renderer from './Renderer';
import Bounds from './Bounds';
import marks from './marks/index';

import {domClear} from './util/dom';
import clip from './util/canvas/clip';
import Canvas from './util/canvas/canvas';
import resize from './util/canvas/resize';
import {inherits} from 'vega-util';

export default function CanvasRenderer(loader) {
  Renderer.call(this, loader);
  this._redraw = false;
}

var prototype = inherits(CanvasRenderer, Renderer),
    base = Renderer.prototype,
    tempBounds = new Bounds();

prototype.initialize = function(el, width, height, origin) {
  this._canvas = Canvas(1, 1); // instantiate a small canvas
  if (el) {
    domClear(el, 0).appendChild(this._canvas);
    this._canvas.setAttribute('class', 'marks');
  }
  // this method will invoke resize to size the canvas appropriately
  return base.initialize.call(this, el, width, height, origin);
};

prototype.resize = function(width, height, origin) {
  base.resize.call(this, width, height, origin);
  resize(this._canvas, this._width, this._height, this._origin);
  return this._redraw = true, this;
};

prototype.canvas = function() {
  return this._canvas;
};

prototype.context = function() {
  return this._canvas ? this._canvas.getContext('2d') : null;
};

function clipToBounds(g, items) {
  var b = new Bounds(), i, n, item, mark, group;
  for (i=0, n=items.length; i<n; ++i) {
    item = items[i];
    mark = item.mark;
    group = mark.group;
    item = marks[mark.marktype].nested ? mark : item;
    b.union(translate(item.bounds, group));
    if (item.bounds_prev) {
      b.union(translate(item.bounds_prev, group));
    }
  }
  b.expand(1).round();

  g.beginPath();
  g.rect(b.x1, b.y1, b.width(), b.height());
  g.clip();

  return b;
}

function translate(bounds, group) {
  if (group == null) return bounds;
  var b = tempBounds.clear().union(bounds);
  for (; group != null; group = group.mark.group) {
    b.translate(group.x || 0, group.y || 0);
  }
  return b;
}

prototype._render = function(scene, items) {
  var g = this.context(),
      o = this._origin,
      w = this._width,
      h = this._height,
      b;

  // setup
  g.save();
  b = (!items || this._redraw)
    ? (this._redraw = false, null)
    : clipToBounds(g, items);
  this.clear(-o[0], -o[1], w, h);

  // render
  this.draw(g, scene, b);

  // takedown
  g.restore();

  return this;
};

prototype.draw = function(ctx, scene, bounds) {
  var mark = marks[scene.marktype];
  if (scene.clip) clip(ctx, scene);
  mark.draw.call(this, ctx, scene, bounds);
  if (scene.clip) ctx.restore();
};

prototype.clear = function(x, y, w, h) {
  var g = this.context();
  g.clearRect(x, y, w, h);
  if (this._bgcolor != null) {
    g.fillStyle = this._bgcolor;
    g.fillRect(x, y, w, h);
  }
};
<commit_msg>Update CanvasRenderer clipping for fractional origin offset.<commit_after>import Renderer from './Renderer';
import Bounds from './Bounds';
import marks from './marks/index';

import {domClear} from './util/dom';
import clip from './util/canvas/clip';
import Canvas from './util/canvas/canvas';
import resize from './util/canvas/resize';
import {inherits} from 'vega-util';

export default function CanvasRenderer(loader) {
  Renderer.call(this, loader);
  this._redraw = false;
}

var prototype = inherits(CanvasRenderer, Renderer),
    base = Renderer.prototype,
    tempBounds = new Bounds();

prototype.initialize = function(el, width, height, origin) {
  this._canvas = Canvas(1, 1); // instantiate a small canvas
  if (el) {
    domClear(el, 0).appendChild(this._canvas);
    this._canvas.setAttribute('class', 'marks');
  }
  // this method will invoke resize to size the canvas appropriately
  return base.initialize.call(this, el, width, height, origin);
};

prototype.resize = function(width, height, origin) {
  base.resize.call(this, width, height, origin);
  resize(this._canvas, this._width, this._height, this._origin);
  return this._redraw = true, this;
};

prototype.canvas = function() {
  return this._canvas;
};

prototype.context = function() {
  return this._canvas ? this._canvas.getContext('2d') : null;
};

function clipToBounds(g, origin, items) {
  var b = new Bounds(), i, n, item, mark, group;
  for (i=0, n=items.length; i<n; ++i) {
    item = items[i];
    mark = item.mark;
    group = mark.group;
    item = marks[mark.marktype].nested ? mark : item;
    b.union(translate(item.bounds, group));
    if (item.bounds_prev) {
      b.union(translate(item.bounds_prev, group));
    }
  }
  b.expand(1).round();
  b.translate(-(origin[0] % 1), -(origin[1] % 1));

  g.beginPath();
  g.rect(b.x1, b.y1, b.width(), b.height());
  g.clip();

  return b;
}

function translate(bounds, group) {
  if (group == null) return bounds;
  var b = tempBounds.clear().union(bounds);
  for (; group != null; group = group.mark.group) {
    b.translate(group.x || 0, group.y || 0);
  }
  return b;
}

prototype._render = function(scene, items) {
  var g = this.context(),
      o = this._origin,
      w = this._width,
      h = this._height,
      b;

  // setup
  g.save();
  b = (!items || this._redraw)
    ? (this._redraw = false, null)
    : clipToBounds(g, o, items);

  this.clear(-o[0], -o[1], w, h);

  // render
  this.draw(g, scene, b);

  // takedown
  g.restore();

  return this;
};

prototype.draw = function(ctx, scene, bounds) {
  var mark = marks[scene.marktype];
  if (scene.clip) clip(ctx, scene);
  mark.draw.call(this, ctx, scene, bounds);
  if (scene.clip) ctx.restore();
};

prototype.clear = function(x, y, w, h) {
  var g = this.context();
  g.clearRect(x, y, w, h);
  if (this._bgcolor != null) {
    g.fillStyle = this._bgcolor;
    g.fillRect(x, y, w, h);
  }
};
<|endoftext|>


<commit_before>var request = require('request');
var cheerio = require('cheerio');
var url = require('url');
var iconv = require('iconv-lite');
var charsetDetector = require("node-icu-charset-detector");

module.exports = function(from, to, uri) {
    if (uri.length === 1) {
        uri = url.parse(uri[0]);
    }else{
        uri = url.parse(uri[1]);
    }
    var options = {
        url: encodeURI(uri.href),
        headers: {
            'User-Agent': 'request',
            'Cookie': 'over18=1',
            'Accept-Language': 'zh-TW,zh;q=0.8,en-US;q=0.5,en;q=0.3'
        },
        timeout: 3000,
        gzip: true,
        encoding: null
    };
    request(options, function(error, response, body) {
        if (!error) {
            body = iconv.decode(body, charsetDetector.detectCharset(body));
            $ = cheerio.load(body);
            var title =$('title').text().trim().replace(/\s/g, ' ');
            if (title != '') {
                /*global oktw*/
                oktw.say(from, to, '[Title] ' + title);
            }
        }
    });
};

module.exports.info = {name:'title', rawcommand:/https?:\/\/\S*/i};

<commit_msg>fix title bug<commit_after>var request = require('request');
var cheerio = require('cheerio');
var url = require('url');
var iconv = require('iconv-lite');
var charsetDetector = require("node-icu-charset-detector");

module.exports = function(from, to, uri) {
    if (uri.length === 1) {
        uri = url.parse(uri[0]);
    }
    else {
        uri = url.parse(uri[1]);
    }
    var options = {
        url: uri.href,
        headers: {
            'User-Agent': 'request',
            'Cookie': 'over18=1',
            'Accept-Language': 'zh-TW,zh;q=0.8,en-US;q=0.5,en;q=0.3'
        },
        timeout: 3000,
        gzip: true,
        encoding: null
    };
    request(options, function(error, response, body) {
        if (!error) {
            body = iconv.decode(body, charsetDetector.detectCharset(body));
            $ = cheerio.load(body);
            var title = $('title').text().trim().replace(/\s/g, ' ');
            if (title != '') {
                /*global oktw*/
                oktw.say(from, to, '[Title] ' + title);
            }
        }
    });
};

module.exports.info = {
    name: 'title',
    rawcommand: /https?:\/\/\S*/i
};
<|endoftext|>


<commit_before>var util = require('util')
var exec = require('child_process').exec;

module.exports = {

    convert: function(){

        var sources = './exports/merge/%05d.jpg';
        var destMP4 = './exports/video.mp4';
        var destOGG = './exports/video.ogg';

        console.log('start video encoding'.cyan);
        /*
         * -i input name
         * -r framerate
         * -y overwrite
         * -qscale 1 > max quality
         */
        //exec("ffmpeg -r 10 -y -qscale 1 -i "+sources+" "+destMP4, function(error, stdout, stderr){
        exec("~/bin/ffmpeg -r 10 -y -i "+sources+" -vcodec libx264 -preset slow -crf 24 -pix_fmt yuv420p "+destMP4+"", function(error, stdout, stderr){
            console.log('MP4 video encoded'.green);

            if (error !== null) {
                console.log('exec error: '.red + error);
            }

            //exec("ffmpeg -r 10 -y -qscale 15 -i "+sources+" "+destOGG, function(error, stdout, stderr){
            exec("~/bin/ffmpeg -r 10 -y -i "+sources+" "+destOGG, function(error, stdout, stderr){
                console.log('OGG video encoded'.green);

                if (error !== null) {
                    console.log('exec error: '.red + error);
                }
            });
        });
    }
};
<commit_msg>Added temp video command<commit_after>var util = require('util')
var exec = require('child_process').exec;

module.exports = {

    convert: function(){

        var sources = './exports/merge/%05d.jpg';
        var destMP4 = './exports/video.mp4';
        var destOGG = './exports/video.ogg';

        console.log('start video encoding'.cyan);
        /*
         * -i input name
         * -r framerate
         * -y overwrite
         * -qscale 1 > max quality
         */
        //exec("ffmpeg -r 10 -y -qscale 1 -i "+sources+" "+destMP4, function(error, stdout, stderr){
        exec("~/bin/ffmpeg -r 10 -y -i "+sources+" -vcodec libx264 -preset slow -crf 24 -pix_fmt yuv420p "+destMP4+"", function(error, stdout, stderr){
            console.log('MP4 video encoded'.green);

            if (error !== null) {
                console.log('exec error: '.red + error);
            }

            //exec("ffmpeg -r 10 -y -qscale 15 -i "+sources+" "+destOGG, function(error, stdout, stderr){
            exec("~/bin/ffmpeg -r 10 -y -i "+sources+" "+destOGG, function(error, stdout, stderr){
                console.log('OGG video encoded'.green);

                if (error !== null) {
                    console.log('exec error: '.red + error);
                }
            });
        });
    }
};
//  /usr/bin/ffmpeg -r 10 -y  -i ./exports/merge/%05d.jpg -qscale 1 ./exports/video.mp4
//  /usr/bin/ffmpeg -r 10 -y  -i ./exports/merge/%05d.jpg -qscale 15 ./exports/video.ogg
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define: false, $: false */

/**
 * PreferencesManager
 *
 */
define(function (require, exports, module) {
    'use strict';

    var PREFERENCES_KEY = "com.adobe.brackets.preferences";

    // Private Properties
    var preferencesKey,
        callbacks = {},
        prefStorage,
        persistentStorage,
        doLoadPreferences   = false;

    /**
     * Retrieves a copy of the client's preferences object.
     *
     * @param {string}  unique identifier clientID
     * @return {object} preference
     */
    function getPreferences(clientID) {
        if ((clientID === undefined) || (clientID === null)) {
            throw new Error("Invalid clientID");
        }

        var prefs = prefStorage[clientID];

        if (prefs === undefined) {
            return undefined;
        }

        // create a deep copy to return to the client
        return JSON.parse(JSON.stringify(prefs));
    }

    /**
     * Saves to persistent storage.
     * TODO (jasonsj): local and/or hosted
     */
    function saveToPersistentStorage() {
        // save all preferences
        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));
    }

    /**
     * Registers a save participant callback for a client. The callback is
     * fired when Brackets quits (window.unload). When fired, callbacks may
     * persist data (e.g. preferences or current state) as valid JSON values
     * to the storage argument.
     *
     * @param {string}          unique identifier clientID for this client
     * @param {function(...)}   callback function
     * @param {object}          optional "this" object for the callback
     * @param {object}          optional default preferences object for this client
     */
    function addPreferencesClient(clientID, callback, instance, defaults) {
        if (typeof callback !== "function") {
            throw new Error("Invalid arguments");
        }

        // attempt to load existing preferences
        var clientPrefs = getPreferences(clientID);

        // if clientPrefs is undefined, try defaults
        if (clientPrefs === undefined) {
            if (JSON.stringify(defaults)) {
                // use defaults if it is a valid JSON object
                clientPrefs = defaults;
            } else {
                // use empty defaults if JSON validation fails
                clientPrefs = {};
            }

            // save defaults in-memory, storage
            prefStorage[clientID] = clientPrefs;
            saveToPersistentStorage();
        }

        var callbackData = { clientID: clientID,
                             callback: callback,
                             instance: instance };

        // add to callbacks list
        callbacks[clientID] = callbackData;
    }

    /**
     * Save all preference clients.
     */
    function savePreferences() {
        var data,
            storage;

        // iterate over all preference clients
        $.each(callbacks, function (index, value) {
            data = callbacks[index];
            storage = getPreferences(data.clientID);

            // fire callback with thisArg and preference storage
            try {
                data.callback.call(data.instance, storage);
            } catch (e) {
                console.log("PreferenceManager.savePreferences(): Failed to save data for clientID " + data.clientID);
            }

            // only save preferences that can be serialized with JSON
            if (JSON.stringify(storage)) {
                prefStorage[data.clientID] = storage;
            }
        });

        saveToPersistentStorage();
    }

    /**
     * @private
     * Reset preferences and callbacks
     */
    function _reset() {
        callbacks = {};
        prefStorage = {};

        // Note that storage.clear() is not used. Production and unit test code
        // both rely on the same backing storage but unique item keys.
        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));
    }

    /**
     * @private
     * Initialize persistent storage implementation
     */
    function _initStorage(storage) {
        persistentStorage = storage;

        if (doLoadPreferences) {
            prefStorage = JSON.parse(persistentStorage.getItem(preferencesKey));
        }

        // initialize empty preferences if none were found in storage
        if (!prefStorage) {
            _reset();
        }
    }

    // check localStorage for a preferencesKey
    preferencesKey = localStorage.getItem("preferencesKey");

    if (!preferencesKey) {
        // use default key if none is found
        preferencesKey = PREFERENCES_KEY;
        doLoadPreferences = true;
    } else {
        // using a non-default key, check for additional settings
        doLoadPreferences = !!(localStorage.getItem("doLoadPreferences"));
    }

    // Use localStorage by default
    _initStorage(localStorage);

    // Public API
    exports.getPreferences          = getPreferences;
    exports.addPreferencesClient    = addPreferencesClient;
    exports.savePreferences         = savePreferences;

    // Internal Use Only
    exports._reset                  = _reset;
});<commit_msg>Remove jQuery from PreferencesManager<commit_after>/*
 * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define: false */

/**
 * PreferencesManager
 *
 */
define(function (require, exports, module) {
    'use strict';

    var PREFERENCES_KEY = "com.adobe.brackets.preferences";

    // Private Properties
    var preferencesKey,
        callbacks = [],
        prefStorage,
        persistentStorage,
        doLoadPreferences   = false;

    /**
     * Retrieves a copy of the client's preferences object.
     *
     * @param {string}  unique identifier clientID
     * @return {object} preference
     */
    function getPreferences(clientID) {
        if ((clientID === undefined) || (clientID === null)) {
            throw new Error("Invalid clientID");
        }

        var prefs = prefStorage[clientID];

        if (prefs === undefined) {
            return undefined;
        }

        // create a deep copy to return to the client
        return JSON.parse(JSON.stringify(prefs));
    }

    /**
     * Saves to persistent storage.
     * TODO (jasonsj): local and/or hosted
     */
    function saveToPersistentStorage() {
        // save all preferences
        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));
    }

    /**
     * Registers a save participant callback for a client. The callback is
     * fired when Brackets quits (window.unload). When fired, callbacks may
     * persist data (e.g. preferences or current state) as valid JSON values
     * to the storage argument.
     *
     * @param {string}          unique identifier clientID for this client
     * @param {function(...)}   callback function
     * @param {object}          optional "this" object for the callback
     * @param {object}          optional default preferences object for this client
     */
    function addPreferencesClient(clientID, callback, instance, defaults) {
        if (typeof callback !== "function") {
            throw new Error("Invalid arguments");
        }

        // attempt to load existing preferences
        var clientPrefs = getPreferences(clientID);

        // if clientPrefs is undefined, try defaults
        if (clientPrefs === undefined) {
            if (JSON.stringify(defaults)) {
                // use defaults if it is a valid JSON object
                clientPrefs = defaults;
            } else {
                // use empty defaults if JSON validation fails
                clientPrefs = {};
            }

            // save defaults in-memory, storage
            prefStorage[clientID] = clientPrefs;
            saveToPersistentStorage();
        }

        var callbackData = { clientID: clientID,
                             callback: callback,
                             instance: instance };

        // add to callbacks list
        callbacks.push(callbackData);
    }

    /**
     * Save all preference clients.
     */
    function savePreferences() {
        var storage;

        // iterate over all preference clients
        callbacks.forEach(function (value, index) {
            storage = getPreferences(value.clientID);

            // fire callback with thisArg and preference storage
            try {
                value.callback.call(value.instance, storage);
            } catch (e) {
                console.log("PreferenceManager.savePreferences(): Failed to save data for clientID " + value.clientID);
            }

            // only save preferences that can be serialized with JSON
            if (JSON.stringify(storage)) {
                prefStorage[value.clientID] = storage;
            }
        });

        saveToPersistentStorage();
    }

    /**
     * @private
     * Reset preferences and callbacks
     */
    function _reset() {
        callbacks = [];
        prefStorage = {};

        // Note that storage.clear() is not used. Production and unit test code
        // both rely on the same backing storage but unique item keys.
        persistentStorage.setItem(preferencesKey, JSON.stringify(prefStorage));
    }

    /**
     * @private
     * Initialize persistent storage implementation
     */
    function _initStorage(storage) {
        persistentStorage = storage;

        if (doLoadPreferences) {
            prefStorage = JSON.parse(persistentStorage.getItem(preferencesKey));
        }

        // initialize empty preferences if none were found in storage
        if (!prefStorage) {
            _reset();
        }
    }

    // check localStorage for a preferencesKey
    preferencesKey = localStorage.getItem("preferencesKey");

    if (!preferencesKey) {
        // use default key if none is found
        preferencesKey = PREFERENCES_KEY;
        doLoadPreferences = true;
    } else {
        // using a non-default key, check for additional settings
        doLoadPreferences = !!(localStorage.getItem("doLoadPreferences"));
    }

    // Use localStorage by default
    _initStorage(localStorage);

    // Public API
    exports.getPreferences          = getPreferences;
    exports.addPreferencesClient    = addPreferencesClient;
    exports.savePreferences         = savePreferences;

    // Internal Use Only
    exports._reset                  = _reset;
});<|endoftext|>


<commit_before>const Mongodb = require('./Mongodb.js');
const dataArr = [{ 'name': '1区-sb兴', 'age': 60 }, { 'name': '2区-sb兴', 'age': 50 }, { 'name': '3区-sb兴', 'age': 40 }, { 'name': '4区-sb兴', 'age': 30 }];

const mongo = new Mongodb({
  db: '汀沙街大瓜兴',
  collection: 'SB兴'
});

mongo.connect(function (db) {
  mongo.insert(db,dataArr);
});

mongo.connect(function (db) {
  mongo.updata(db, { 'name': '1区-sb兴' },{$set:{'sex':女}});
});

// mongo.connect(function (db) {
//   mongo.delete(db, { 'name': '1区-sb兴' });
// });

mongo.connect(function (db) {
  mongo.find(db, function (result) {
    console.log(result);
  });
});
<commit_msg>mongodb<commit_after>const Mongodb = require('./Mongodb.js');
const dataArr = [{ 'name': '1区-sb兴', 'age': 60 }, { 'name': '2区-sb兴', 'age': 50 }, { 'name': '3区-sb兴', 'age': 40 }, { 'name': '4区-sb兴', 'age': 30 }];

const mongo = new Mongodb({
  db: '汀沙街大瓜兴',
  collection: 'SB兴'
});

mongo.connect(function (db) {
  mongo.insert(db,dataArr);
});

mongo.connect(function (db) {
  mongo.updata(db, { 'name': '1区-sb兴' },{$set:{'sex':'女'}});
});

// mongo.connect(function (db) {
//   mongo.delete(db, { 'name': '1区-sb兴' });
// });

mongo.connect(function (db) {
  mongo.find(db, function (result) {
    console.log(result);
  });
});
<|endoftext|>


<commit_before>const { EventEmitter } = require('events');
const createDebugger = require('debug');
const compose = require('composition');
const async = require('async');
const assert = require('assert');
const Client = require('./Client');
const Context = require('./Context');
const { inspect } = require('util');

const debug = createDebugger('wexx:server');

class Application extends EventEmitter {
  constructor() {
    super();
    this.middleware = [];
    this.clients = [];
    this.use = this.middleware.push.bind(this.middleware);
    this.clientCounter = 0;
  }

  handler(context) {
    const composed = compose([this.respond, ...this.middleware]);

    composed
      .call(context)
      .then(null, error => {
        debug(`error from middleware:\n${error.stack}`);
        assert(context.respond !== false);
        assert(context.result === undefined);
        assert(context.error === undefined);
        context.error = 'Internal error';
        this.respondWithError.call(context);
      })
      .catch(error => {
        debug(`error in error handler:\n${error.stack}`);
      });
  }

  respondWithError() {
    let { error } = this;
    assert(error, 'error missing');

    if (typeof error === 'string') {
      error = { message: error };
    }

    this.client.send({
      id: this.message.id,
      error,
    });
  }

  *respond(next) {
    // Run last
    yield next;

    assert(this.respond !== false);

    let { error } = this;
    const { result } = this;

    if (!error && this.result === undefined) {
      this.error = { message: 'Unhandled request' };
    }

    if (this.error) {
      this.application.respondWithError.call(this);
      return;
    }

    this.client.send({
      id: this.message.id,
      result,
    });
  }

  onClientMessage(client, message) {
    const context = new Context({
      client,
      message,
      application: this,
    });

    this.handler(context);
  }

  onClientClose(client) {
    debug(`removing closed client from clients list`);
    const removed = !!this.clients.splice(this.clients.indexOf(client), 1);
    assert(removed, 'failed to remove closed client');
  }

  notifyAll(method, params = {}) {
    const message = { method, params };
    debug(
      `notifying all: ${inspect(message)} (${this.clients.length} clients)`
    );

    this.clients.forEach(client => {
      client.send(message);
    });
  }

  // TODO: Extract into a listener
  accept(socket) {
    debug('accepting client');

    const client = new Client(socket);
    client.id = ++this.clientCounter;
    this.clients.push(client);
    client.on('message', this.onClientMessage.bind(this, client));
    client.on('close', this.onClientClose.bind(this, client));
  }
}

module.exports = Application;
<commit_msg>Return accepted client<commit_after>const { EventEmitter } = require('events');
const createDebugger = require('debug');
const compose = require('composition');
const async = require('async');
const assert = require('assert');
const Client = require('./Client');
const Context = require('./Context');
const { inspect } = require('util');

const debug = createDebugger('wexx:server');

class Application extends EventEmitter {
  constructor() {
    super();
    this.middleware = [];
    this.clients = [];
    this.use = this.middleware.push.bind(this.middleware);
    this.clientCounter = 0;
  }

  handler(context) {
    const composed = compose([this.respond, ...this.middleware]);

    composed
      .call(context)
      .then(null, error => {
        debug(`error from middleware:\n${error.stack}`);
        assert(context.respond !== false);
        assert(context.result === undefined);
        assert(context.error === undefined);
        context.error = 'Internal error';
        this.respondWithError.call(context);
      })
      .catch(error => {
        debug(`error in error handler:\n${error.stack}`);
      });
  }

  respondWithError() {
    let { error } = this;
    assert(error, 'error missing');

    if (typeof error === 'string') {
      error = { message: error };
    }

    this.client.send({
      id: this.message.id,
      error,
    });
  }

  *respond(next) {
    // Run last
    yield next;

    assert(this.respond !== false);

    let { error } = this;
    const { result } = this;

    if (!error && this.result === undefined) {
      this.error = { message: 'Unhandled request' };
    }

    if (this.error) {
      this.application.respondWithError.call(this);
      return;
    }

    this.client.send({
      id: this.message.id,
      result,
    });
  }

  onClientMessage(client, message) {
    const context = new Context({
      client,
      message,
      application: this,
    });

    this.handler(context);
  }

  onClientClose(client) {
    debug(`removing closed client from clients list`);
    const removed = !!this.clients.splice(this.clients.indexOf(client), 1);
    assert(removed, 'failed to remove closed client');
  }

  notifyAll(method, params = {}) {
    const message = { method, params };
    debug(
      `notifying all: ${inspect(message)} (${this.clients.length} clients)`
    );

    this.clients.forEach(client => {
      client.send(message);
    });
  }

  // TODO: Extract into a listener
  accept(socket) {
    debug('accepting client');

    const client = new Client(socket);
    client.id = ++this.clientCounter;
    this.clients.push(client);
    client.on('message', this.onClientMessage.bind(this, client));
    client.on('close', this.onClientClose.bind(this, client));

    return client;
  }
}

module.exports = Application;
<|endoftext|>


<commit_before>/**
 * @ngdoc object
 * @name ng.$cacheFactory
 *
 * @description
 * Factory that constructs cache objects.
 *
 *
 * @param {string} cacheId Name or id of the newly created cache.
 * @param {object=} options Options object that specifies the cache behavior. Properties:
 *
 *   - `{number=}` `capacity` — turns the cache into LRU cache.
 *
 * @returns {object} Newly created cache object with the following set of methods:
 *
 * - `{object}` `info()` — Returns id, size, and options of cache.
 * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it.
 * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
 * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
 * - `{void}` `removeAll()` — Removes all cached values.
 * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
 *
 */
function $CacheFactoryProvider() {

  this.$get = function() {
    var caches = {};

    function cacheFactory(cacheId, options) {
      if (cacheId in caches) {
        throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
      }

      var size = 0,
          stats = extend({}, options, {id: cacheId}),
          data = {},
          capacity = (options && options.capacity) || Number.MAX_VALUE,
          lruHash = {},
          freshEnd = null,
          staleEnd = null;

      return caches[cacheId] = {

        put: function(key, value) {
          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});

          refresh(lruEntry);

          if (isUndefined(value)) return;
          if (!(key in data)) size++;
          data[key] = value;

          if (size > capacity) {
            this.remove(staleEnd.key);
          }

          return value;
        },

        get: function(key) {
          var lruEntry = lruHash[key];

          if (!lruEntry) return;

          refresh(lruEntry);

          return data[key];
        },

        remove: function(key) {
          var lruEntry = lruHash[key];

          if (!lruEntry) return;

          if (lruEntry == freshEnd) freshEnd = lruEntry.p;
          if (lruEntry == staleEnd) staleEnd = lruEntry.n;
          link(lruEntry.n,lruEntry.p);

          delete lruHash[key];
          delete data[key];
          size--;
        },

        removeAll: function() {
          data = {};
          size = 0;
          lruHash = {};
          freshEnd = staleEnd = null;
        },

        destroy: function() {
          data = null;
          stats = null;
          lruHash = null;
          delete caches[cacheId];
        },

        info: function() {
          return extend({}, stats, {size: size});
        }
      };

      /**
       * makes the `entry` the freshEnd of the LRU linked list
       */
      function refresh(entry) {
        if (entry != freshEnd) {
          if (!staleEnd) {
            staleEnd = entry;
          } else if (staleEnd == entry) {
            staleEnd = entry.n;
          }

          link(entry.n, entry.p);
          link(entry, freshEnd);
          freshEnd = entry;
          freshEnd.n = null;
        }
      }

      /**
       * bidirectionally links two entries of the LRU linked list
       */
      function link(nextEntry, prevEntry) {
        if (nextEntry != prevEntry) {
          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
        }
      }
    }

    cacheFactory.info = function() {
      var info = {};
      forEach(caches, function(cache, cacheId) {
        info[cacheId] = cache.info();
      });
      return info;
    };

    cacheFactory.get = function(cacheId) {
      return caches[cacheId];
    };

    return cacheFactory;
  };
}

/**
 * @ngdoc object
 * @name ng.$templateCache
 *
 * @description
 * Cache used for storing html templates.
 *
 * See {@link ng.$cacheFactory $cacheFactory}.
 *
 */
function $TemplateCacheProvider() {
  this.$get = ['$cacheFactory', function($cacheFactory) {
    return $cacheFactory('templates');
  }];
}

<commit_msg>docs($cacheFactory): show that you can access existing caches<commit_after>/**
 * @ngdoc object
 * @name ng.$cacheFactory
 *
 * @description
 * Factory that constructs cache objects and gives access to them.
 *
 * <pre>
 *
 *  var cache = $cacheFactory('cacheId');
 *  expect($cacheFactory.get('cacheId')).toBe(cache);
 *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
 *
 *  cache.put("key", "value");
 *  cache.put("another key", "another value");
 *
 *  expect(cache.info()).toEqual({id: 'cacheId', size: 2}); // Since we've specified no options on creation
 *
 * </pre>
 *
 *
 * @param {string} cacheId Name or id of the newly created cache.
 * @param {object=} options Options object that specifies the cache behavior. Properties:
 *
 *   - `{number=}` `capacity` — turns the cache into LRU cache.
 *
 * @returns {object} Newly created cache object with the following set of methods:
 *
 * - `{object}` `info()` — Returns id, size, and options of cache.
 * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it.
 * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
 * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
 * - `{void}` `removeAll()` — Removes all cached values.
 * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
 *
 */
function $CacheFactoryProvider() {

  this.$get = function() {
    var caches = {};

    function cacheFactory(cacheId, options) {
      if (cacheId in caches) {
        throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
      }

      var size = 0,
          stats = extend({}, options, {id: cacheId}),
          data = {},
          capacity = (options && options.capacity) || Number.MAX_VALUE,
          lruHash = {},
          freshEnd = null,
          staleEnd = null;

      return caches[cacheId] = {

        put: function(key, value) {
          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});

          refresh(lruEntry);

          if (isUndefined(value)) return;
          if (!(key in data)) size++;
          data[key] = value;

          if (size > capacity) {
            this.remove(staleEnd.key);
          }

          return value;
        },

        get: function(key) {
          var lruEntry = lruHash[key];

          if (!lruEntry) return;

          refresh(lruEntry);

          return data[key];
        },

        remove: function(key) {
          var lruEntry = lruHash[key];

          if (!lruEntry) return;

          if (lruEntry == freshEnd) freshEnd = lruEntry.p;
          if (lruEntry == staleEnd) staleEnd = lruEntry.n;
          link(lruEntry.n,lruEntry.p);

          delete lruHash[key];
          delete data[key];
          size--;
        },

        removeAll: function() {
          data = {};
          size = 0;
          lruHash = {};
          freshEnd = staleEnd = null;
        },

        destroy: function() {
          data = null;
          stats = null;
          lruHash = null;
          delete caches[cacheId];
        },

        info: function() {
          return extend({}, stats, {size: size});
        }
      };

      /**
       * makes the `entry` the freshEnd of the LRU linked list
       */
      function refresh(entry) {
        if (entry != freshEnd) {
          if (!staleEnd) {
            staleEnd = entry;
          } else if (staleEnd == entry) {
            staleEnd = entry.n;
          }

          link(entry.n, entry.p);
          link(entry, freshEnd);
          freshEnd = entry;
          freshEnd.n = null;
        }
      }

      /**
       * bidirectionally links two entries of the LRU linked list
       */
      function link(nextEntry, prevEntry) {
        if (nextEntry != prevEntry) {
          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
        }
      }
    }

  /**
   * @ngdoc method
   * @name ng.$cacheFactory#info
   * @methodOf ng.$cacheFactory
   *
   * @description
   * Get information about all the of the caches that have been created
   *
   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
   */
    cacheFactory.info = function() {
      var info = {};
      forEach(caches, function(cache, cacheId) {
        info[cacheId] = cache.info();
      });
      return info;
    };

  /**
   * @ngdoc method
   * @name ng.$cacheFactory#get
   * @methodOf ng.$cacheFactory
   *
   * @description
   * Get access to a cache object by the `cacheId` used when it was created.
   *
   * @param {string} cacheId Name or id of a cache to access.
   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
   */
    cacheFactory.get = function(cacheId) {
      return caches[cacheId];
    };

    return cacheFactory;
  };
}

/**
 * @ngdoc object
 * @name ng.$templateCache
 *
 * @description
 * Cache used for storing html templates.
 *
 * See {@link ng.$cacheFactory $cacheFactory}.
 *
 */
function $TemplateCacheProvider() {
  this.$get = ['$cacheFactory', function($cacheFactory) {
    return $cacheFactory('templates');
  }];
}

<|endoftext|>