<commit_before>import getFiles from './get-files';
import hash from './hash';
import retry from './retry';
import bytes from 'bytes';
import Agent from './agent';
import EventEmitter from 'events';
import { basename, resolve } from 'path';
import { stat, readFile } from 'fs-promise';
import resumer from 'resumer';
import splitArray from 'split-array';

// limit of size of files to find
const ONEMB = bytes('1mb');

// how many concurrent HTTP/2 stream uploads
const MAX_CONCURRENT = 10;

// check if running windows
const IS_WIN = /^win/.test(process.platform);
const SEP = IS_WIN ? '\\' : '/';

export default class Now extends EventEmitter {
  constructor (url, token, { forceNew = false, debug = false }) {
    super();
    this._token = token;
    this._debug = debug;
    this._forceNew = forceNew;
    this._agent = new Agent(url, { debug });
    this._onRetry = this._onRetry.bind(this);
  }

  async create (path, { forceNew, forceSync }) {
    this._path = path;

    try {
      await stat(path);
    } catch (err) {
      throw new Error(`Could not read directory ${path}.`);
    }

    let pkg;
    try {
      pkg = await readFile(resolve(path, 'package.json'));
      pkg = JSON.parse(pkg);
    } catch (err) {
      const e = Error(`Failed to read JSON in "${path}/package.json"`);
      e.userError = true;
      throw e;
    }

    if (null == pkg.name || 'string' !== typeof pkg.name) {
      const e = Error('Missing or invalid `name` in `package.json`.');
      e.userError = true;
      throw e;
    }

    if (!pkg.scripts || (!pkg.scripts.start && !pkg.scripts['now-start'])) {
      const e = Error('Missing `start` (or `now-start`) script in `package.json`. ' +
        'See: https://docs.npmjs.com/cli/start.');
      e.userError = true;
      throw e;
    }

    if (this._debug) console.time('> [debug] Getting files');
    const files = await getFiles(path, pkg, { limit: ONEMB, debug: this._debug });
    if (this._debug) console.timeEnd('> [debug] Getting files');

    if (this._debug) console.time('> [debug] Computing hashes');
    const hashes = await hash(files);
    if (this._debug) console.timeEnd('> [debug] Computing hashes');

    this._files = hashes;

    const deployment = await retry(async (bail) => {
      if (this._debug) console.time('> [debug] /create');
      const res = await this._fetch('/create', {
        method: 'POST',
        body: {
          forceNew,
          forceSync,
          name: pkg.name || basename(path),
          description: pkg.description,
          files: Array.from(this._files).map(([sha, { data, name }]) => {
            return {
              sha,
              size: data.length,
              file: toRelative(name, this._path)
            };
          })
        }
      });
      if (this._debug) console.timeEnd('> [debug] /create');

      // no retry on 4xx
      if (200 !== res.status && (400 <= res.status && 500 > res.status)) {
        if (this._debug) {
          console.log('> [debug] bailing on creating due to %s', res.status);
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Deployment initialization failed');
      }

      return res.json();
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    this._id = deployment.deploymentId;
    this._host = deployment.url;
    this._missing = deployment.missing || [];

    return this._url;
  }

  upload () {
    const parts = splitArray(this._missing, MAX_CONCURRENT);

    if (this._debug) {
      console.log('> [debug] Will upload ' +
        `${this._missing.length} files in ${parts.length} ` +
        `steps of ${MAX_CONCURRENT} uploads.`);
    }

    const uploadChunk = () => {
      Promise.all(parts.shift().map((sha) => retry(async (bail) => {
        const file = this._files.get(sha);
        const { data, name } = file;

        if (this._debug) console.time(`> [debug] /sync ${name}`);

        const stream = resumer().queue(data).end();
        const res = await this._fetch('/sync', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/octet-stream',
            'Content-Length': data.length,
            'x-now-deployment-id': this._id,
            'x-now-sha': sha,
            'x-now-file': toRelative(name, this._path),
            'x-now-size': data.length
          },
          body: stream
        });
        if (this._debug) console.timeEnd(`> [debug] /sync ${name}`);

        // no retry on 4xx
        if (200 !== res.status && (400 <= res.status || 500 > res.status)) {
          if (this._debug) console.log('> [debug] bailing on creating due to %s', res.status);
          return bail(responseError(res));
        }

        this.emit('upload', file);
      }, { retries: 5, randomize: true, onRetry: this._onRetry })))
      .then(() => parts.length ? uploadChunk() : this.emit('complete'))
      .catch((err) => this.emit('error', err));
    };

    uploadChunk();
  }

  async list (app) {
    const query = app ? `?app=${encodeURIComponent(app)}` : '';

    const { deployments } = await retry(async (bail) => {
      if (this._debug) console.time('> [debug] /list');
      const res = await this._fetch('/list' + query);
      if (this._debug) console.timeEnd('> [debug] /list');

      // no retry on 4xx
      if (400 <= res.status && 500 > res.status) {
        if (this._debug) {
          console.log('> [debug] bailing on listing due to %s', res.status);
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Fetching deployment list failed');
      }

      return res.json();
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    return deployments;
  }

  async remove (deploymentId) {
    await retry(async (bail) => {
      if (this._debug) console.time('> [debug] /remove');
      const res = await this._fetch('/remove', {
        method: 'DELETE'
      });
      if (this._debug) console.timeEnd('> [debug] /remove');

      // no retry on 4xx
      if (400 <= res.status && 500 > res.status) {
        if (this._debug) {
          console.log('> [debug] bailing on listing due to %s', res.status);
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Removing deployment failed');
      }
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    return true;
  }

  _onRetry (err) {
    if (this._debug) {
      console.log(`> [debug] Retrying: ${err.stack}`);
    }
  }

  close () {
    this._agent.close();
  }

  get id () {
    return this._id;
  }

  get url () {
    return `https://${this._host}`;
  }

  get host () {
    return this._host;
  }

  get syncAmount () {
    if (!this._syncAmount) {
      this._syncAmount = this._missing
      .map((sha) => this._files.get(sha).data.length)
      .reduce((a, b) => a + b, 0);
    }
    return this._syncAmount;
  }

  async _fetch (_url, opts = {}) {
    opts.headers = opts.headers || {};
    opts.headers.authorization = `Bearer ${this._token}`;
    return await this._agent.fetch(_url, opts);
  }
}

function toRelative (path, base) {
  const fullBase = base.endsWith(SEP) ? base + SEP : base;
  const relative = path.substr(fullBase.length);
  if (relative.startsWith(SEP)) return relative.substr(1);
  return relative;
}

function responseError (res) {
  const err = new Error('Response error');
  err.status = res.status;

  if (429 === res.status) {
    const retryAfter = res.headers.get('Retry-After');
    if (retryAfter) {
      err.retryAfter = parseInt(retryAfter, 10);
    }
  }

  return err;
}
<commit_msg>Fix body<commit_after>import getFiles from './get-files';
import hash from './hash';
import retry from './retry';
import bytes from 'bytes';
import Agent from './agent';
import EventEmitter from 'events';
import { basename, resolve } from 'path';
import { stat, readFile } from 'fs-promise';
import resumer from 'resumer';
import splitArray from 'split-array';

// limit of size of files to find
const ONEMB = bytes('1mb');

// how many concurrent HTTP/2 stream uploads
const MAX_CONCURRENT = 10;

// check if running windows
const IS_WIN = /^win/.test(process.platform);
const SEP = IS_WIN ? '\\' : '/';

export default class Now extends EventEmitter {
  constructor (url, token, { forceNew = false, debug = false }) {
    super();
    this._token = token;
    this._debug = debug;
    this._forceNew = forceNew;
    this._agent = new Agent(url, { debug });
    this._onRetry = this._onRetry.bind(this);
  }

  async create (path, { forceNew, forceSync }) {
    this._path = path;

    try {
      await stat(path);
    } catch (err) {
      throw new Error(`Could not read directory ${path}.`);
    }

    let pkg;
    try {
      pkg = await readFile(resolve(path, 'package.json'));
      pkg = JSON.parse(pkg);
    } catch (err) {
      const e = Error(`Failed to read JSON in "${path}/package.json"`);
      e.userError = true;
      throw e;
    }

    if (null == pkg.name || 'string' !== typeof pkg.name) {
      const e = Error('Missing or invalid `name` in `package.json`.');
      e.userError = true;
      throw e;
    }

    if (!pkg.scripts || (!pkg.scripts.start && !pkg.scripts['now-start'])) {
      const e = Error('Missing `start` (or `now-start`) script in `package.json`. ' +
        'See: https://docs.npmjs.com/cli/start.');
      e.userError = true;
      throw e;
    }

    if (this._debug) console.time('> [debug] Getting files');
    const files = await getFiles(path, pkg, { limit: ONEMB, debug: this._debug });
    if (this._debug) console.timeEnd('> [debug] Getting files');

    if (this._debug) console.time('> [debug] Computing hashes');
    const hashes = await hash(files);
    if (this._debug) console.timeEnd('> [debug] Computing hashes');

    this._files = hashes;

    const deployment = await retry(async (bail) => {
      if (this._debug) console.time('> [debug] /create');
      const res = await this._fetch('/create', {
        method: 'POST',
        body: {
          forceNew,
          forceSync,
          name: pkg.name || basename(path),
          description: pkg.description,
          files: Array.from(this._files).map(([sha, { data, name }]) => {
            return {
              sha,
              size: data.length,
              file: toRelative(name, this._path)
            };
          })
        }
      });
      if (this._debug) console.timeEnd('> [debug] /create');

      // no retry on 4xx
      if (200 !== res.status && (400 <= res.status && 500 > res.status)) {
        if (this._debug) {
          console.log('> [debug] bailing on creating due to %s', res.status);
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Deployment initialization failed');
      }

      return res.json();
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    this._id = deployment.deploymentId;
    this._host = deployment.url;
    this._missing = deployment.missing || [];

    return this._url;
  }

  upload () {
    const parts = splitArray(this._missing, MAX_CONCURRENT);

    if (this._debug) {
      console.log('> [debug] Will upload ' +
        `${this._missing.length} files in ${parts.length} ` +
        `steps of ${MAX_CONCURRENT} uploads.`);
    }

    const uploadChunk = () => {
      Promise.all(parts.shift().map((sha) => retry(async (bail) => {
        const file = this._files.get(sha);
        const { data, name } = file;

        if (this._debug) console.time(`> [debug] /sync ${name}`);

        const stream = resumer().queue(data).end();
        const res = await this._fetch('/sync', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/octet-stream',
            'Content-Length': data.length,
            'x-now-deployment-id': this._id,
            'x-now-sha': sha,
            'x-now-file': toRelative(name, this._path),
            'x-now-size': data.length
          },
          body: stream
        });
        if (this._debug) console.timeEnd(`> [debug] /sync ${name}`);

        // no retry on 4xx
        if (200 !== res.status && (400 <= res.status || 500 > res.status)) {
          if (this._debug) console.log('> [debug] bailing on creating due to %s', res.status);
          return bail(responseError(res));
        }

        this.emit('upload', file);
      }, { retries: 5, randomize: true, onRetry: this._onRetry })))
      .then(() => parts.length ? uploadChunk() : this.emit('complete'))
      .catch((err) => this.emit('error', err));
    };

    uploadChunk();
  }

  async list (app) {
    const query = app ? `?app=${encodeURIComponent(app)}` : '';

    const { deployments } = await retry(async (bail) => {
      if (this._debug) console.time('> [debug] /list');
      const res = await this._fetch('/list' + query);
      if (this._debug) console.timeEnd('> [debug] /list');

      // no retry on 4xx
      if (400 <= res.status && 500 > res.status) {
        if (this._debug) {
          console.log('> [debug] bailing on listing due to %s', res.status);
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Fetching deployment list failed');
      }

      return res.json();
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    return deployments;
  }

  async remove (deploymentId) {
    const data = { deploymentId };

    await retry(async (bail) => {
      if (this._debug) console.time('> [debug] /remove');
      const res = await this._fetch('/remove', {
        method: 'DELETE',
        body: data
      });
      if (this._debug) console.timeEnd('> [debug] /remove');

      // no retry on 4xx
      if (400 <= res.status && 500 > res.status) {
        if (this._debug) {
          console.log('> [debug] bailing on listing due to %s', res.status);
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Removing deployment failed');
      }
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    return true;
  }

  _onRetry (err) {
    if (this._debug) {
      console.log(`> [debug] Retrying: ${err.stack}`);
    }
  }

  close () {
    this._agent.close();
  }

  get id () {
    return this._id;
  }

  get url () {
    return `https://${this._host}`;
  }

  get host () {
    return this._host;
  }

  get syncAmount () {
    if (!this._syncAmount) {
      this._syncAmount = this._missing
      .map((sha) => this._files.get(sha).data.length)
      .reduce((a, b) => a + b, 0);
    }
    return this._syncAmount;
  }

  async _fetch (_url, opts = {}) {
    opts.headers = opts.headers || {};
    opts.headers.authorization = `Bearer ${this._token}`;
    return await this._agent.fetch(_url, opts);
  }
}

function toRelative (path, base) {
  const fullBase = base.endsWith(SEP) ? base + SEP : base;
  const relative = path.substr(fullBase.length);
  if (relative.startsWith(SEP)) return relative.substr(1);
  return relative;
}

function responseError (res) {
  const err = new Error('Response error');
  err.status = res.status;

  if (429 === res.status) {
    const retryAfter = res.headers.get('Retry-After');
    if (retryAfter) {
      err.retryAfter = parseInt(retryAfter, 10);
    }
  }

  return err;
}
<|endoftext|>


<commit_before>var Lexer = require("./lexer")
  , Parser = require("./parser")
  , Compiler = require('./compiler')
  , fs = require('fs')
  , path = require('path')
  , _ = require('underscore');

module.exports = {

  Lexer: Lexer,
  Parser: Parser,
  Compiler: Compiler,

  render: function (source, options) {
    options = opts(options)
    var compiler = new this.Compiler(source, options);
    return compiler.compile()(options);
  },

  renderFile: function (filename, options) {
    options = opts(options, filename);
    return this.render(fs.readFileSync(filename, options.encoding), options);
  },

  compile: function (source, options) {
    var compiler = new this.Compiler(source, opts(options));
    return compiler.compile();
  },

  compileFile: function (filename, options) {
    options = opts(options, filename);
    return this.compile(fs.readFileSync(filename, options.encoding), options);
  }

};

function opts(options, filename) {
  var defaults = { encoding: 'utf8', basepath: __dirname };
  if (filename) { defaults.basepath = path.dirname(filename); }
  return _.defaults((options || {}), defaults);
}
<commit_msg>missing semicolon<commit_after>var Lexer = require("./lexer")
  , Parser = require("./parser")
  , Compiler = require('./compiler')
  , fs = require('fs')
  , path = require('path')
  , _ = require('underscore');

module.exports = {

  Lexer: Lexer,
  Parser: Parser,
  Compiler: Compiler,

  render: function (source, options) {
    options = opts(options);
    var compiler = new this.Compiler(source, options);
    return compiler.compile()(options);
  },

  renderFile: function (filename, options) {
    options = opts(options, filename);
    return this.render(fs.readFileSync(filename, options.encoding), options);
  },

  compile: function (source, options) {
    var compiler = new this.Compiler(source, opts(options));
    return compiler.compile();
  },

  compileFile: function (filename, options) {
    options = opts(options, filename);
    return this.compile(fs.readFileSync(filename, options.encoding), options);
  }

};

function opts(options, filename) {
  var defaults = { encoding: 'utf8', basepath: __dirname };
  if (filename) { defaults.basepath = path.dirname(filename); }
  return _.defaults((options || {}), defaults);
}
<|endoftext|>


<commit_before>'use strict';

const Filter = require('broccoli-persistent-filter');
const CLIEngine = require('eslint').CLIEngine;
const defaultsDeep = require('lodash.defaultsdeep');
const md5Hex = require('md5-hex');
const stringify = require('json-stable-stringify');
const path = require('path');
const concat = require('broccoli-concat');

const isString = require('./is-string');
const getResultSeverity = require('./get-result-severity');
const testGenerators = require('./test-generators');
const testGeneratorNames = Object.keys(testGenerators);

const FACTORY_METHOD_USED = Symbol('create() factory method was used');

function resolveInputDirectory(inputNode) {
  if (typeof inputNode === 'string') {
    return inputNode;
  }

  // eslint-disable-next-line no-underscore-dangle
  const nodeInfo = inputNode.__broccoliGetInfo__();

  if (nodeInfo.nodeType === 'source') {
    return nodeInfo.sourceDirectory;
  }

  if (nodeInfo.inputNodes.length > 1) {
    // eslint-disable-next-line max-len
    throw new Error('EslintValidationFilter can only handle one:* broccoli nodes, but part of the given input pipeline is a many:* node. (broccoli-merge-trees is an example of a many:* node) Please perform many:* operations after linting.');
  }

  return resolveInputDirectory(nodeInfo.inputNodes[0]);
}

/**
 * Uses the content of each file in a given node and runs eslint validation on it.
 * @param {Object} inputNode Node from broccoli.makeTree
 * @param {{format: String, options: EslintOptions}} options Filter options
 * @returns {EslintValidationFilter} Filter obconfig @constructor
 */
function EslintValidationFilter(inputNode, options) {
  if (!(this instanceof EslintValidationFilter)) {
    return new EslintValidationFilter(inputNode, options);
  }

  let _console = options.console || console;

  if (!options[FACTORY_METHOD_USED]) {
    throw new Error('Please use the create() factory method instead of ' +
      'calling ESLint() directly or using new ESLint()');
  }

  options = defaultsDeep({}, options, {
    persist: true,
    extensions: ['js'],
    options: {
      ignore: true,
    },
  });

  this.extensions = options.extensions;

  // call base class constructor
  Filter.call(this, inputNode, options);

  this.internalOptions = options;

  // set formatter
  if (typeof this.internalOptions.format === 'function') {
    this.formatter = this.internalOptions.format;
  } else {
    // eslint-disable-next-line global-require
    this.formatter = require(this.internalOptions.format || 'eslint/lib/formatters/stylish');
  }

  this.console = _console;

  this.cli = new CLIEngine(options.options);

  this.eslintrc = resolveInputDirectory(inputNode);

  if (isString(this.internalOptions.testGenerator)) {
    this.testGenerator = testGenerators[this.internalOptions.testGenerator];
    if (this.internalOptions.group && this.testGenerator) {
      this.testGenerator = this.testGenerator.testOnly;
    }
    if (!this.testGenerator) {
      throw new Error(`Could not find '${this.internalOptions.testGenerator}' test generator.`);
    }
  } else {
    this.testGenerator = this.internalOptions.testGenerator;
  }

  if (this.testGenerator) {
    this.targetExtension = 'lint-test.js';
  }
}

module.exports = EslintValidationFilter;
EslintValidationFilter.prototype = Object.create(Filter.prototype);
EslintValidationFilter.prototype.constructor = EslintValidationFilter;
EslintValidationFilter.prototype.targetExtension = 'js';

EslintValidationFilter.prototype.baseDir = function baseDir() {
  return path.join(__dirname, '..');
};

EslintValidationFilter.prototype.cacheKeyProcessString = function cacheKeyProcessString(content, relativePath) {
  function functionStringifier(key, value) {
    if (typeof value === 'function') {
      return value.toString();
    }
    return value;
  }

  const filePath = path.join(this.eslintrc, relativePath);
  const isIgnoredFile = this.cli.isPathIgnored(filePath);

  return md5Hex([
    content,
    relativePath,
    isIgnoredFile.toString(),
    stringify(this.internalOptions, { replacer: functionStringifier }),
    stringify(this.cli.getConfigForFile(filePath))
  ]);
};

EslintValidationFilter.prototype.getDestFilePath = function getDestFilePath(relativePath) {
  //This method gets called for all files in the tree, so we call the superclass to filter
  //based on the extensions property.
  const filterPath = Filter.prototype.getDestFilePath.apply(this, arguments);
  const fullPath = path.join(this.eslintrc, relativePath);

  if (filterPath && !this.cli.isPathIgnored(fullPath)) {
    return filterPath;
  } else {
    return null;
  }
};

EslintValidationFilter.prototype.processString = function processString(content, relativePath) {
  // verify file content
  const configPath = path.join(this.eslintrc, relativePath);
  const report = this.cli.executeOnText(content, configPath);

  const toCache = { report, output: content };

  if (this.testGenerator && Array.isArray(report.results)) {
    const result = report.results[0] || {};
    const messages = result.messages || [];

    toCache.output = this.testGenerator(relativePath, messages, result);
  }

  return toCache;
};

/**
 * Post-process the filtered output, calculating the result severity from the report
 * if the option to `throwOnError` has been set
 *
 * @param {Object} results A results object returned from `processString`
 * @param {Object} results.report The report returned from this.cli.executeOnText()
 * @param {string} results.output The original file content passed to `processString` -- or the
 *      result of executing the a provided `testGenerator` function on the `report`
 *
 * @returns {Object} An object with an `.output` property, which will be
 *    used as the emitted file contents
 */
EslintValidationFilter.prototype.postProcess = function postProcess(results /* , relativePath */) {
  let report = results.report;

  // if verification has result
  if (report.results.length &&
      report.results[0].messages.length) {

    // log formatter output
    this.console.log(this.formatter(report.results));

    const throwOnWarn = !!this.internalOptions.throwOnWarn;
    const throwOnError = !!this.internalOptions.throwOnError;

    if (throwOnWarn || throwOnError) {
      const resultSeverity = getResultSeverity(report.results[0].messages);

      if (resultSeverity === 1 && throwOnWarn) {
        throw new Error('rules violation with `warn` severity level');
      }

      if (resultSeverity >= 2 && (throwOnWarn || throwOnError)) {
        throw new Error('rules violation with `error` severity level');
      }
    }
  }

  return { output: results.output };
};

/**
 * Factory function that allows to return something different
 * instead of a single EslintValidationFilter.
 *
 * @experimental
 */
EslintValidationFilter.create = function(inputNode, _options) {
  let options = Object.assign({}, _options, {
    [FACTORY_METHOD_USED]: true
  });

  if (!options.group) {
    return new EslintValidationFilter(inputNode, options);
  }

  if (typeof options.testGenerator !== 'string' || testGeneratorNames.indexOf(options.testGenerator) === -1) {
    throw new Error(`The "group" options can only be used with a "testGenerator" option of: ${testGeneratorNames}`);
  }

  let testGenerator = testGenerators[options.testGenerator];

  let header = testGenerator.header(options.group);
  let footer = testGenerator.footer();

  let eslint = new EslintValidationFilter(inputNode, options);

  return concat(eslint, {
    outputFile: `/${options.group}.lint-test.js`,
    header,
    inputFiles: ['**/*.lint-test.js'],
    footer,
    sourceMapConfig: { enabled: false },
    allowNone: true,
  });
};

Object.defineProperty(EslintValidationFilter, 'testGenerators', {
  get() {
    return testGeneratorNames.slice(0);
  }
});
<commit_msg>Remove deprecated code allowing `ESLint(...)` invocation without `new`<commit_after>'use strict';

const Filter = require('broccoli-persistent-filter');
const CLIEngine = require('eslint').CLIEngine;
const defaultsDeep = require('lodash.defaultsdeep');
const md5Hex = require('md5-hex');
const stringify = require('json-stable-stringify');
const path = require('path');
const concat = require('broccoli-concat');

const isString = require('./is-string');
const getResultSeverity = require('./get-result-severity');
const testGenerators = require('./test-generators');
const testGeneratorNames = Object.keys(testGenerators);

const FACTORY_METHOD_USED = Symbol('create() factory method was used');

function resolveInputDirectory(inputNode) {
  if (typeof inputNode === 'string') {
    return inputNode;
  }

  // eslint-disable-next-line no-underscore-dangle
  const nodeInfo = inputNode.__broccoliGetInfo__();

  if (nodeInfo.nodeType === 'source') {
    return nodeInfo.sourceDirectory;
  }

  if (nodeInfo.inputNodes.length > 1) {
    // eslint-disable-next-line max-len
    throw new Error('EslintValidationFilter can only handle one:* broccoli nodes, but part of the given input pipeline is a many:* node. (broccoli-merge-trees is an example of a many:* node) Please perform many:* operations after linting.');
  }

  return resolveInputDirectory(nodeInfo.inputNodes[0]);
}

/**
 * Uses the content of each file in a given node and runs eslint validation on it.
 * @param {Object} inputNode Node from broccoli.makeTree
 * @param {{format: String, options: EslintOptions}} options Filter options
 * @returns {EslintValidationFilter} Filter obconfig @constructor
 */
function EslintValidationFilter(inputNode, options) {
  let _console = options.console || console;

  if (!options[FACTORY_METHOD_USED]) {
    throw new Error('Please use the create() factory method instead of ' +
      'calling ESLint() directly or using new ESLint()');
  }

  options = defaultsDeep({}, options, {
    persist: true,
    extensions: ['js'],
    options: {
      ignore: true,
    },
  });

  this.extensions = options.extensions;

  // call base class constructor
  Filter.call(this, inputNode, options);

  this.internalOptions = options;

  // set formatter
  if (typeof this.internalOptions.format === 'function') {
    this.formatter = this.internalOptions.format;
  } else {
    // eslint-disable-next-line global-require
    this.formatter = require(this.internalOptions.format || 'eslint/lib/formatters/stylish');
  }

  this.console = _console;

  this.cli = new CLIEngine(options.options);

  this.eslintrc = resolveInputDirectory(inputNode);

  if (isString(this.internalOptions.testGenerator)) {
    this.testGenerator = testGenerators[this.internalOptions.testGenerator];
    if (this.internalOptions.group && this.testGenerator) {
      this.testGenerator = this.testGenerator.testOnly;
    }
    if (!this.testGenerator) {
      throw new Error(`Could not find '${this.internalOptions.testGenerator}' test generator.`);
    }
  } else {
    this.testGenerator = this.internalOptions.testGenerator;
  }

  if (this.testGenerator) {
    this.targetExtension = 'lint-test.js';
  }
}

module.exports = EslintValidationFilter;
EslintValidationFilter.prototype = Object.create(Filter.prototype);
EslintValidationFilter.prototype.constructor = EslintValidationFilter;
EslintValidationFilter.prototype.targetExtension = 'js';

EslintValidationFilter.prototype.baseDir = function baseDir() {
  return path.join(__dirname, '..');
};

EslintValidationFilter.prototype.cacheKeyProcessString = function cacheKeyProcessString(content, relativePath) {
  function functionStringifier(key, value) {
    if (typeof value === 'function') {
      return value.toString();
    }
    return value;
  }

  const filePath = path.join(this.eslintrc, relativePath);
  const isIgnoredFile = this.cli.isPathIgnored(filePath);

  return md5Hex([
    content,
    relativePath,
    isIgnoredFile.toString(),
    stringify(this.internalOptions, { replacer: functionStringifier }),
    stringify(this.cli.getConfigForFile(filePath))
  ]);
};

EslintValidationFilter.prototype.getDestFilePath = function getDestFilePath(relativePath) {
  //This method gets called for all files in the tree, so we call the superclass to filter
  //based on the extensions property.
  const filterPath = Filter.prototype.getDestFilePath.apply(this, arguments);
  const fullPath = path.join(this.eslintrc, relativePath);

  if (filterPath && !this.cli.isPathIgnored(fullPath)) {
    return filterPath;
  } else {
    return null;
  }
};

EslintValidationFilter.prototype.processString = function processString(content, relativePath) {
  // verify file content
  const configPath = path.join(this.eslintrc, relativePath);
  const report = this.cli.executeOnText(content, configPath);

  const toCache = { report, output: content };

  if (this.testGenerator && Array.isArray(report.results)) {
    const result = report.results[0] || {};
    const messages = result.messages || [];

    toCache.output = this.testGenerator(relativePath, messages, result);
  }

  return toCache;
};

/**
 * Post-process the filtered output, calculating the result severity from the report
 * if the option to `throwOnError` has been set
 *
 * @param {Object} results A results object returned from `processString`
 * @param {Object} results.report The report returned from this.cli.executeOnText()
 * @param {string} results.output The original file content passed to `processString` -- or the
 *      result of executing the a provided `testGenerator` function on the `report`
 *
 * @returns {Object} An object with an `.output` property, which will be
 *    used as the emitted file contents
 */
EslintValidationFilter.prototype.postProcess = function postProcess(results /* , relativePath */) {
  let report = results.report;

  // if verification has result
  if (report.results.length &&
      report.results[0].messages.length) {

    // log formatter output
    this.console.log(this.formatter(report.results));

    const throwOnWarn = !!this.internalOptions.throwOnWarn;
    const throwOnError = !!this.internalOptions.throwOnError;

    if (throwOnWarn || throwOnError) {
      const resultSeverity = getResultSeverity(report.results[0].messages);

      if (resultSeverity === 1 && throwOnWarn) {
        throw new Error('rules violation with `warn` severity level');
      }

      if (resultSeverity >= 2 && (throwOnWarn || throwOnError)) {
        throw new Error('rules violation with `error` severity level');
      }
    }
  }

  return { output: results.output };
};

/**
 * Factory function that allows to return something different
 * instead of a single EslintValidationFilter.
 *
 * @experimental
 */
EslintValidationFilter.create = function(inputNode, _options) {
  let options = Object.assign({}, _options, {
    [FACTORY_METHOD_USED]: true
  });

  if (!options.group) {
    return new EslintValidationFilter(inputNode, options);
  }

  if (typeof options.testGenerator !== 'string' || testGeneratorNames.indexOf(options.testGenerator) === -1) {
    throw new Error(`The "group" options can only be used with a "testGenerator" option of: ${testGeneratorNames}`);
  }

  let testGenerator = testGenerators[options.testGenerator];

  let header = testGenerator.header(options.group);
  let footer = testGenerator.footer();

  let eslint = new EslintValidationFilter(inputNode, options);

  return concat(eslint, {
    outputFile: `/${options.group}.lint-test.js`,
    header,
    inputFiles: ['**/*.lint-test.js'],
    footer,
    sourceMapConfig: { enabled: false },
    allowNone: true,
  });
};

Object.defineProperty(EslintValidationFilter, 'testGenerators', {
  get() {
    return testGeneratorNames.slice(0);
  }
});
<|endoftext|>


<commit_before>// Constructor
var AnsiParser = module.exports = {};

/**
 * parse
 * Parses the string containing ANSI styles.
 *
 * @name parse
 * @function
 * @param {String} input The input string.
 * @return {Array} An array of object like below:
 *
 *  ```js
 *  [
 *    {
 *        style: "\u00\u001b[1m\u001b[38;5;231",
 *        content: "H"
 *    },
 *    {
 *       style: "\u00\u001b[1m\u001b[38;5;231",
 *       content: "e"
 *    },
 *    ...
 *  ]
 *  ```
 */
AnsiParser.parse = function (input) {

    var i = 0;
    if (Array.isArray(input)) {
        var arr = [];
        for (i = 0; i < input.length; ++i) {
            arr.push(AnsiParser.parse(input[i]));
        }
        return arr;
    }

    if (typeof input !== "string") {
        throw new Error("Input is not a string.");
    }

    var noAnsi = AnsiParser.removeAnsi(input);
    if (input === noAnsi) {
        return input.split("").map(function (c) {
            return {
                style: ""
              , content: c
            };
        });
    }

    var result = [];
    for (i = 0; i < noAnsi.length; ++i) {
        result.push(AnsiParser.getAtIndex(input, noAnsi, i));
    }

    return result;
};

/**
 * getAtIndex
 * Returns the content and ANSI style at known index.
 *
 * @name getAtIndex
 * @function
 * @param {String} input The input string.
 * @param {String} noAnsi The input string without containing ansi styles.
 * @param {Number} index The character index.
 * @return {Object} An object containing the following fields:
 *
 *  - `style` (String): The ANSI style at provided index.
 *  - `content` (String): The content (character) at provided index.
 */
AnsiParser.getAtIndex = function (input, noAnsi, index) {

    if (typeof noAnsi === "number") {
        index = noAnsi;
        noAnsi = AnsiParser.removeAnsi(input);
    }

    if (input === noAnsi) {
        return {
            style: ""
          , content: noAnsi[index]
        };
    }

    var sIndex = 0
      , eIndex = index
      , color=[]
      , cmatch
      ;

    while (sIndex < input.length) {
        cmatch = input.substr(sIndex).match(/^(\u001B\[[^m]*m)/);
        if (cmatch) {
            if (cmatch[0] == '\x1B[0m') {
                color = [];
            } else {
                color.push(cmatch[0]);
            }
            sIndex += cmatch[0].length;
        } else {
            if (!eIndex) {
                break;
            }
            ++sIndex;
            --eIndex;
        }
    }

    return {
        style: color.join("")
      , content: noAnsi[index]
    };
};

/**
 * removeAnsi
 * Removes ANSI styles from the input string.
 *
 * @name removeAnsi
 * @function
 * @param {String} input The input string.
 * @return {String} The string without ANSI styles.
 */
AnsiParser.removeAnsi = function (input) {
    return input.replace(/\u001b\[.*?m/g, "");
};

/**
 * stringify
 * Stringifies an array of objects in the format defined by `AnsiParser`.
 *
 * @name stringify
 * @function
 * @param {Array} arr The input array.
 * @return {String} The stringified input array.
 */
AnsiParser.stringify = function (arr) {

    var str = ""
      , cArr = null
      , i = 0
      ;

    if (arr && Array.isArray(arr[0])) {
        for (; i < arr.length; ++i) {
            str += AnsiParser.stringify(arr[i]) + "\n";
        }
        return str;
    }

    var lastStyle = ""
      , cStyle = ""
      ;

    for (; i < arr.length; ++i) {
        cArr = arr[i];

        cStyle = cArr.style;
        if (cStyle === lastStyle) {
            cStyle = "";
        } else {
            lastStyle = cStyle;
        }

        str += cStyle + cArr.content;
        if (cArr.content === "\n") {
            str += "\u001b[0m";
        }
    }

    str += "\u001b[0m";

    return str;
};

/**
 * addChar
 * Adds a new char into array.
 *
 * @name addChar
 * @function
 * @param {Array} arr The input array.
 * @param {String} c The char to add.
 * @param {String} s ANSI start style.
 * @param {String} e ANSI end style.
 * @return {undefined}
 */
AnsiParser.addChar = function (arr, c, s, e) {
    arr.push({
        start: s || ""
      , content: c
      , start: e || ""
    });
};
<commit_msg>Fixed #4. Optimized parsing.<commit_after>// Constructor
var AnsiParser = module.exports = {};

/**
 * parse
 * Parses the string containing ANSI styles.
 *
 * @name parse
 * @function
 * @param {String} input The input string.
 * @return {Array} An array of object like below:
 *
 *  ```js
 *  [
 *    {
 *        style: "\u00\u001b[1m\u001b[38;5;231",
 *        content: "H"
 *    },
 *    {
 *       style: "\u00\u001b[1m\u001b[38;5;231",
 *       content: "e"
 *    },
 *    ...
 *  ]
 *  ```
 */
AnsiParser.parse = function (input) {

    var i = 0;
    if (Array.isArray(input)) {
        var arr = [];
        for (i = 0; i < input.length; ++i) {
            arr.push(AnsiParser.parse(input[i]));
        }
        return arr;
    }

    if (typeof input !== "string") {
        throw new Error("Input is not a string.");
    }

    var noAnsi = AnsiParser.removeAnsi(input);
    if (input === noAnsi) {
        return input.split("").map(function (c) {
            return {
                style: ""
              , content: c
            };
        });
    }

    var result = []
      , sIndex = 0
      , cmatch
      , color = []
      ;

    i = 0;
    while (sIndex < input.length) {
        cmatch = input.substr(sIndex).match(/^(\u001B\[[^m]*m)/);
        if (cmatch) {
            if (cmatch[0] == '\x1B[0m') {
                color = [];
            } else {
                if (/^\u001b\[38;5/.test(cmatch[0]) && /^\u001b\[38;5/.test(color.slice(-1)[0])) {
                    color.splice(-1);
                }
                color.push(cmatch[0]);
            }
            sIndex += cmatch[0].length;
        } else {
            result.push({
                style: color.join("")
              , content: noAnsi[i++]
            });
            ++sIndex;
        }
    }

    return result;
};

/**
 * getAtIndex
 * Returns the content and ANSI style at known index.
 *
 * @name getAtIndex
 * @function
 * @param {String} input The input string.
 * @param {String} noAnsi The input string without containing ansi styles.
 * @param {Number} index The character index.
 * @return {Object} An object containing the following fields:
 *
 *  - `style` (String): The ANSI style at provided index.
 *  - `content` (String): The content (character) at provided index.
 */
AnsiParser.getAtIndex = function (input, noAnsi, index) {

    if (typeof noAnsi === "number") {
        index = noAnsi;
        noAnsi = AnsiParser.removeAnsi(input);
    }

    if (input === noAnsi) {
        return {
            style: ""
          , content: noAnsi[index]
        };
    }

    var sIndex = 0
      , eIndex = index
      , color=[]
      , cmatch
      ;

    while (sIndex < input.length) {
        cmatch = input.substr(sIndex).match(/^(\u001B\[[^m]*m)/);
        if (cmatch) {
            if (cmatch[0] == '\x1B[0m') {
                color = [];
            } else {
                if (/^\u001b\[38;5/.test(cmatch[0]) && /^\u001b\[38;5/.test(color.slice(-1)[0])) {
                    color.splice(-1);
                }
                color.push(cmatch[0]);
            }
            sIndex += cmatch[0].length;
        } else {
            if (!eIndex) {
                break;
            }
            ++sIndex;
            --eIndex;
        }
    }

    return {
        style: color.join("")
      , content: noAnsi[index]
    };
};

/**
 * removeAnsi
 * Removes ANSI styles from the input string.
 *
 * @name removeAnsi
 * @function
 * @param {String} input The input string.
 * @return {String} The string without ANSI styles.
 */
AnsiParser.removeAnsi = function (input) {
    return input.replace(/\u001b\[.*?m/g, "");
};

/**
 * stringify
 * Stringifies an array of objects in the format defined by `AnsiParser`.
 *
 * @name stringify
 * @function
 * @param {Array} arr The input array.
 * @return {String} The stringified input array.
 */
AnsiParser.stringify = function (arr) {

    var str = ""
      , cArr = null
      , i = 0
      ;

    if (arr && Array.isArray(arr[0])) {
        for (; i < arr.length; ++i) {
            str += AnsiParser.stringify(arr[i]) + "\n";
        }
        return str;
    }

    var lastStyle = ""
      , cStyle = ""
      ;

    for (; i < arr.length; ++i) {
        cArr = arr[i];

        cStyle = cArr.style;
        if (cStyle === lastStyle) {
            cStyle = "";
        } else {
            lastStyle = cStyle;
        }

        str += cStyle + cArr.content;
        if (cArr.content === "\n") {
            str += "\u001b[0m";
        }
    }

    str += "\u001b[0m";

    return str;
};

/**
 * addChar
 * Adds a new char into array.
 *
 * @name addChar
 * @function
 * @param {Array} arr The input array.
 * @param {String} c The char to add.
 * @param {String} s ANSI start style.
 * @param {String} e ANSI end style.
 * @return {undefined}
 */
AnsiParser.addChar = function (arr, c, s, e) {
    arr.push({
        start: s || ""
      , content: c
      , start: e || ""
    });
};
<|endoftext|>


<commit_before>var docxReader = require("./docx-reader");
var DocumentConverter = require("./document-to-html").DocumentConverter;
var htmlPaths = require("./html-paths");
var documentMatchers = require("./document-matchers");
var style = require("./style-reader").readStyle;

exports.Converter = Converter;
exports.read = read;
exports.convertDocumentToHtml = convertDocumentToHtml;
exports.htmlPaths = htmlPaths;
exports.standardOptions = {
    styleMap: [
        style("p.Heading1 => h1"),
        style("p.Heading2 => h2"),
        style("p.Heading3 => h3"),
        style("p.Heading4 => h4"),
        style("p:unordered-list(1) => ul > li:fresh"),
        style("p:ordered-list(1) => ol > li:fresh")
    ]
};

function Converter(options) {
    this._options = options;
}

Converter.prototype.convertToHtml = function(inputOptions) {
    var options = this._options;
    return read(inputOptions)
        .then(function(documentResult) {
            return convertDocumentToHtml(documentResult, options);
        });
}

function read(inputOptions) {
    return docxReader.read(inputOptions);
}

function convertDocumentToHtml(documentResult, options) {
    var documentConverter = new DocumentConverter(options);
    return documentResult.flatMapThen(function(document) {
        return documentConverter.convertToHtml(document);
    });
}
<commit_msg>Add styles for nested lists<commit_after>var docxReader = require("./docx-reader");
var DocumentConverter = require("./document-to-html").DocumentConverter;
var htmlPaths = require("./html-paths");
var documentMatchers = require("./document-matchers");
var style = require("./style-reader").readStyle;

exports.Converter = Converter;
exports.read = read;
exports.convertDocumentToHtml = convertDocumentToHtml;
exports.htmlPaths = htmlPaths;
exports.standardOptions = {
    styleMap: [
        style("p.Heading1 => h1"),
        style("p.Heading2 => h2"),
        style("p.Heading3 => h3"),
        style("p.Heading4 => h4"),
        style("p:unordered-list(1) => ul > li:fresh"),
        style("p:unordered-list(2) => ul|ol > li > ul > li:fresh"),
        style("p:unordered-list(3) => ul|ol > li > ul|ol > li > ul > li:fresh"),
        style("p:unordered-list(4) => ul|ol > li > ul|ol > li > ul|ol > li > ul > li:fresh"),
        style("p:unordered-list(5) => ul|ol > li > ul|ol > li > ul|ol > li > ul|ol > li > ul > li:fresh"),
        style("p:ordered-list(1) => ol > li:fresh"),
        style("p:ordered-list(2) => ul|ol > li > ol > li:fresh"),
        style("p:ordered-list(3) => ul|ol > li > ul|ol > li > ol > li:fresh"),
        style("p:ordered-list(4) => ul|ol > li > ul|ol > li > ul|ol > li > ol > li:fresh"),
        style("p:ordered-list(5) => ul|ol > li > ul|ol > li > ul|ol > li > ul|ol > li > ol > li:fresh")
    ]
};

function Converter(options) {
    this._options = options;
}

Converter.prototype.convertToHtml = function(inputOptions) {
    var options = this._options;
    return read(inputOptions)
        .then(function(documentResult) {
            return convertDocumentToHtml(documentResult, options);
        });
}

function read(inputOptions) {
    return docxReader.read(inputOptions);
}

function convertDocumentToHtml(documentResult, options) {
    var documentConverter = new DocumentConverter(options);
    return documentResult.flatMapThen(function(document) {
        return documentConverter.convertToHtml(document);
    });
}
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
var fs = require('fs');

// Helper for mapping include file paths to karma file patterns - served, included, but not watched
var createIncludePattern = function(path) {
  return {
    pattern: path,
    included: true,
    served: true,
    watched: false
  };
};

// Resolve paths for dependencies now
var getDependencyPath = function(module, relativePath) {
  try {
    return path.dirname(require.resolve(module)) + relativePath;
  } catch (e) {
    if (e.code === 'MODULE_NOT_FOUND' && e.message.indexOf(module) !== -1) {
      console.warn('Cannot find "%s".\n  Did you forget to install it ?\n' +
      '  npm install %s --save-dev', module, module);
    } else {
      console.warn('Error during loading "%s":\n  %s', module, e.message);
    }
  }
};

// Loads up a SystemJS config file and returns the configuration
// Taken from how systemjs-builder loads config files inside node
var readConfigFile = function(filePath) {
  var curSystem = global.System;
  var fileConfig = {};
  global.System = {
    config: function(cfg) {
      fileConfig = cfg;
    }
  };
  // jshint evil:true
  new Function(fs.readFileSync(filePath).toString()).call(global);
  global.System = curSystem;
  return fileConfig;
};

// Takes properties from one object and applies them to another IF they don't already exist
var merge = function(from, into) {
  for (var key in from) {
    if (from.hasOwnProperty(key)) {
      if (!into.hasOwnProperty(key)) {
        into[key] = from[key];
      }
    }
  }
};

// Merges 2 SystemJS configs
var mergeConfigs = function(from, into) {
  merge(from, into);
  merge(from.paths, into.paths);
  merge(from.map, into.map);
  merge(from.meta, into.meta);
};

// Returns a dependency path based on 'paths' configuration, or node_modules/ lookup
var pathOrNpm = function(systemjsConfig, basePath, module, npmPath) {
  var path = systemjsConfig.paths[module];
  if (path) {
    return basePath + systemjsConfig.baseURL + path;
  } else {
    return getDependencyPath(module, npmPath);
  }
};

/**
 * Run during karma initialisation.
 * Alters the karma configuration to use SystemJS.
 * @param config {object}
 */
var initSystemjs = function(config) {
  // Final files array should look like this:
  // - SystemJS libraries - included
  // - SystemJS config - included & watched
  // - App code and tests - served and watched
  // - Plugin adapter - included

  var kSystemjsConfig = config.systemjs || {};
  kSystemjsConfig.config = kSystemjsConfig.config || {};
  var basePath = (config.basePath || '.') + '/';

  // If there's an external SystemJS configuration file...
  if (kSystemjsConfig.configFile) {
    // Add it's path to config.files
    var cfgPath = basePath + kSystemjsConfig.configFile;
    config.files.unshift({
      pattern: cfgPath,
      included: true,
      served: true,
      watched: true
    });

    // Load it, and merge it with the config
    mergeConfigs(readConfigFile(cfgPath), kSystemjsConfig.config);
  }

  // Resolve the paths for es6-module-loader and systemjs
  // Check the System config for the paths, or revert to looking them up in node_modules/
  var es6LoaderPath = pathOrNpm(kSystemjsConfig.config, basePath,
    'es6-module-loader', '/dist/es6-module-loader.src.js');
  var systemjsPath = pathOrNpm(kSystemjsConfig.config, basePath,
    'systemjs', '/system.src.js');

  // Adds dependencies to start of config.files: es6-module-loader, and system.js
  // Don't watch, since these files should never change
  config.files.unshift(
    createIncludePattern(es6LoaderPath),
    createIncludePattern(systemjsPath)
  );

  // Default to use Traceur as transpiler, but make it possible to avoid using
  // a transpiler by setting the transpiler option to null.
  var useTranspiler = kSystemjsConfig.config.transpiler !== null;
  if (useTranspiler) {
    var transpilerPath = kSystemjsConfig.config.transpiler === 'babel' ?
      pathOrNpm(kSystemjsConfig.config, basePath, 'babel', '/node_modules/babel-core/browser.js') :
      pathOrNpm(kSystemjsConfig.config, basePath, 'traceur', '/../../bin/traceur.js');

    // Don't watch, since this file should never change
    config.files.unshift(
      createIncludePattern(transpilerPath)
    );
  }

  // system.js-0.16 uses Function.prototype.bind, which PhantomJS does not support.
  if (config.browsers && config.browsers.indexOf('PhantomJS') !== -1) {
    var phantomjsPolyfillPath = getDependencyPath('phantomjs-polyfill', '/bind-polyfill.js');
    config.files.unshift(
      createIncludePattern(phantomjsPolyfillPath)
    );
  }

  // Adds file patterns from config.systemjs.files to config.files, set to be served but not included
  if (kSystemjsConfig.files) {
    kSystemjsConfig.files.forEach(function(filePath) {
      config.files.push({
        pattern: basePath + filePath,
        included: false,
        served: true,
        watched: true
      });
    });
  }

  // Adds karma-systemjs adapter.js to end of config.files
  config.files.push(createIncludePattern(__dirname + '/adapter.js'));

  // Adding configuration to be passed to the adapter running on the browser
  config.client.systemjs = {
    testFileSuffix: kSystemjsConfig.testFileSuffix,
    config: kSystemjsConfig.config
  };
};
initSystemjs.$inject = ['config'];

module.exports = {
  'framework:systemjs': ['factory', initSystemjs]
};
<commit_msg>Fixed when `paths` is undefined<commit_after>'use strict';
var path = require('path');
var fs = require('fs');

// Helper for mapping include file paths to karma file patterns - served, included, but not watched
var createIncludePattern = function(path) {
  return {
    pattern: path,
    included: true,
    served: true,
    watched: false
  };
};

// Resolve paths for dependencies now
var getDependencyPath = function(moduleName, relativePath) {
  try {
    return path.dirname(require.resolve(moduleName)) + relativePath;
  } catch (e) {
    if (e.code === 'MODULE_NOT_FOUND' && e.message.indexOf(moduleName) !== -1) {
      console.warn('Cannot find "%s".\n  Did you forget to install it ?\n' +
      '  npm install %s --save-dev', moduleName, moduleName);
    } else {
      console.warn('Error during loading "%s":\n  %s', moduleName, e.message);
    }
  }
};

// Loads up a SystemJS config file and returns the configuration
// Taken from how systemjs-builder loads config files inside node
var readConfigFile = function(filePath) {
  var curSystem = global.System;
  var fileConfig = {};
  global.System = {
    config: function(cfg) {
      fileConfig = cfg;
    }
  };
  // jshint evil:true
  new Function(fs.readFileSync(filePath).toString()).call(global);
  global.System = curSystem;
  return fileConfig;
};

// Takes properties from one object and applies them to another IF they don't already exist
var merge = function(source, into) {
  for (var key in source) {
    if (source.hasOwnProperty(key)) {
      if (!into.hasOwnProperty(key)) {
        into[key] = source[key];
      }
    }
  }
};

// Merges 2 SystemJS configs
var mergeConfigs = function(source, into) {
  merge(source, into);
  merge(source.paths, into.paths);
  merge(source.map, into.map);
  merge(source.meta, into.meta);
};

// Returns a dependency path based on 'paths' configuration, or node_modules/ lookup
var pathOrNpm = function(systemjsConfig, basePath, moduleName, npmPath) {
  var path = systemjsConfig.paths && systemjsConfig.paths[moduleName];
  if (path) {
    return basePath + systemjsConfig.baseURL + path;
  } else {
    return getDependencyPath(moduleName, npmPath);
  }
};

/**
 * Run during karma initialisation.
 * Alters the karma configuration to use SystemJS.
 * @param config {object}
 */
var initSystemjs = function(config) {
  // Final files array should look like this:
  // - SystemJS libraries - included
  // - SystemJS config - included & watched
  // - App code and tests - served and watched
  // - Plugin adapter - included

  var kSystemjsConfig = config.systemjs || {};
  kSystemjsConfig.config = kSystemjsConfig.config || {};
  var basePath = (config.basePath || '.') + '/';

  // If there's an external SystemJS configuration file...
  if (kSystemjsConfig.configFile) {
    // Add it's path to config.files
    var cfgPath = basePath + kSystemjsConfig.configFile;
    config.files.unshift({
      pattern: cfgPath,
      included: true,
      served: true,
      watched: true
    });

    // Load it, and merge it with the config
    mergeConfigs(readConfigFile(cfgPath), kSystemjsConfig.config);
  }

  // Resolve the paths for es6-module-loader and systemjs
  // Check the System config for the paths, or revert to looking them up in node_modules/
  var es6LoaderPath = pathOrNpm(kSystemjsConfig.config, basePath,
    'es6-module-loader', '/dist/es6-module-loader.src.js');
  var systemjsPath = pathOrNpm(kSystemjsConfig.config, basePath,
    'systemjs', '/system.src.js');

  // Adds dependencies to start of config.files: es6-module-loader, and system.js
  // Don't watch, since these files should never change
  config.files.unshift(
    createIncludePattern(es6LoaderPath),
    createIncludePattern(systemjsPath)
  );

  // Default to use Traceur as transpiler, but make it possible to avoid using
  // a transpiler by setting the transpiler option to null.
  var useTranspiler = kSystemjsConfig.config.transpiler !== null;
  if (useTranspiler) {
    var transpilerPath = kSystemjsConfig.config.transpiler === 'babel' ?
      pathOrNpm(kSystemjsConfig.config, basePath, 'babel', '/node_modules/babel-core/browser.js') :
      pathOrNpm(kSystemjsConfig.config, basePath, 'traceur', '/../../bin/traceur.js');

    // Don't watch, since this file should never change
    config.files.unshift(
      createIncludePattern(transpilerPath)
    );
  }

  // system.js-0.16 uses Function.prototype.bind, which PhantomJS does not support.
  if (config.browsers && config.browsers.indexOf('PhantomJS') !== -1) {
    var phantomjsPolyfillPath = getDependencyPath('phantomjs-polyfill', '/bind-polyfill.js');
    config.files.unshift(
      createIncludePattern(phantomjsPolyfillPath)
    );
  }

  // Adds file patterns from config.systemjs.files to config.files, set to be served but not included
  if (kSystemjsConfig.files) {
    kSystemjsConfig.files.forEach(function(filePath) {
      config.files.push({
        pattern: basePath + filePath,
        included: false,
        served: true,
        watched: true
      });
    });
  }

  // Adds karma-systemjs adapter.js to end of config.files
  config.files.push(createIncludePattern(__dirname + '/adapter.js'));

  // Adding configuration to be passed to the adapter running on the browser
  config.client.systemjs = {
    testFileSuffix: kSystemjsConfig.testFileSuffix,
    config: kSystemjsConfig.config
  };
};
initSystemjs.$inject = ['config'];

module.exports = {
  'framework:systemjs': ['factory', initSystemjs]
};
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var http = require('http');
var read = require('fs').readFileSync;
var path = require('path');
var exists = require('fs').existsSync;
var engine = require('engine.io');
var client = require('socket.io-client');
var clientVersion = require('socket.io-client/package').version;
var Client = require('./client');
var Emitter = require('events').EventEmitter;
var Namespace = require('./namespace');
var Adapter = require('socket.io-adapter');
var parser = require('socket.io-parser');
var debug = require('debug')('socket.io:server');
var url = require('url');

/**
 * Module exports.
 */

module.exports = Server;

/**
 * Socket.IO client source.
 */

var clientSource = undefined;
var clientSourceMap = undefined;

/**
 * Server constructor.
 *
 * @param {http.Server|Number|Object} srv http server, port or options
 * @param {Object} [opts]
 * @api public
 */

function Server(srv, opts){
  if (!(this instanceof Server)) return new Server(srv, opts);
  if ('object' == typeof srv && srv instanceof Object && !srv.listen) {
    opts = srv;
    srv = null;
  }
  opts = opts || {};
  this.nsps = {};
  this.path(opts.path || '/socket.io');
  this.serveClient(false !== opts.serveClient);
  this.parser = opts.parser || parser;
  this.encoder = new this.parser.Encoder();
  this.adapter(opts.adapter || Adapter);
  this.origins(opts.origins || '*:*');
  this.sockets = this.of('/');
  if (srv) this.attach(srv, opts);
}

/**
 * Server request verification function, that checks for allowed origins
 *
 * @param {http.IncomingMessage} req request
 * @param {Function} fn callback to be called with the result: `fn(err, success)`
 */

Server.prototype.checkRequest = function(req, fn) {
  var origin = req.headers.origin || req.headers.referer;

  // file:// URLs produce a null Origin which can't be authorized via echo-back
  if ('null' == origin || null == origin) origin = '*';

  if (!!origin && typeof(this._origins) == 'function') return this._origins(origin, fn);
  if (this._origins.indexOf('*:*') !== -1) return fn(null, true);
  if (origin) {
    try {
      var parts = url.parse(origin);
      var defaultPort = 'https:' == parts.protocol ? 443 : 80;
      parts.port = parts.port != null
        ? parts.port
        : defaultPort;
      var ok =
        ~this._origins.indexOf(parts.hostname + ':' + parts.port) ||
        ~this._origins.indexOf(parts.hostname + ':*') ||
        ~this._origins.indexOf('*:' + parts.port);
      return fn(null, !!ok);
    } catch (ex) {
    }
  }
  fn(null, false);
};

/**
 * Sets/gets whether client code is being served.
 *
 * @param {Boolean} v whether to serve client code
 * @return {Server|Boolean} self when setting or value when getting
 * @api public
 */

Server.prototype.serveClient = function(v){
  if (!arguments.length) return this._serveClient;
  this._serveClient = v;
  var resolvePath = function(file){
    var filepath = path.resolve(__dirname, './../../', file);
    if (exists(filepath)) {
      return filepath;
    }
    return require.resolve(file);
  };
  if (v && !clientSource) {
    clientSource = read(resolvePath( 'socket.io-client/dist/socket.io.min.js'), 'utf-8');
    try {
      clientSourceMap = read(resolvePath( 'socket.io-client/dist/socket.io.js.map'), 'utf-8');
    } catch(err) {
      debug('could not load sourcemap file');
    }
  }
  return this;
};

/**
 * Old settings for backwards compatibility
 */

var oldSettings = {
  "transports": "transports",
  "heartbeat timeout": "pingTimeout",
  "heartbeat interval": "pingInterval",
  "destroy buffer size": "maxHttpBufferSize"
};

/**
 * Backwards compatibility.
 *
 * @api public
 */

Server.prototype.set = function(key, val){
  if ('authorization' == key && val) {
    this.use(function(socket, next) {
      val(socket.request, function(err, authorized) {
        if (err) return next(new Error(err));
        if (!authorized) return next(new Error('Not authorized'));
        next();
      });
    });
  } else if ('origins' == key && val) {
    this.origins(val);
  } else if ('resource' == key) {
    this.path(val);
  } else if (oldSettings[key] && this.eio[oldSettings[key]]) {
    this.eio[oldSettings[key]] = val;
  } else {
    console.error('Option %s is not valid. Please refer to the README.', key);
  }

  return this;
};

/**
 * Sets the client serving path.
 *
 * @param {String} v pathname
 * @return {Server|String} self when setting or value when getting
 * @api public
 */

Server.prototype.path = function(v){
  if (!arguments.length) return this._path;
  this._path = v.replace(/\/$/, '');
  return this;
};

/**
 * Sets the adapter for rooms.
 *
 * @param {Adapter} v pathname
 * @return {Server|Adapter} self when setting or value when getting
 * @api public
 */

Server.prototype.adapter = function(v){
  if (!arguments.length) return this._adapter;
  this._adapter = v;
  for (var i in this.nsps) {
    if (this.nsps.hasOwnProperty(i)) {
      this.nsps[i].initAdapter();
    }
  }
  return this;
};

/**
 * Sets the allowed origins for requests.
 *
 * @param {String} v origins
 * @return {Server|Adapter} self when setting or value when getting
 * @api public
 */

Server.prototype.origins = function(v){
  if (!arguments.length) return this._origins;

  this._origins = v;
  return this;
};

/**
 * Attaches socket.io to a server or port.
 *
 * @param {http.Server|Number} server or port
 * @param {Object} options passed to engine.io
 * @return {Server} self
 * @api public
 */

Server.prototype.listen =
Server.prototype.attach = function(srv, opts){
  if ('function' == typeof srv) {
    var msg = 'You are trying to attach socket.io to an express ' +
    'request handler function. Please pass a http.Server instance.';
    throw new Error(msg);
  }

  // handle a port as a string
  if (Number(srv) == srv) {
    srv = Number(srv);
  }

  if ('number' == typeof srv) {
    debug('creating http server and binding to %d', srv);
    var port = srv;
    srv = http.Server(function(req, res){
      res.writeHead(404);
      res.end();
    });
    srv.listen(port);

  }

  // set engine.io path to `/socket.io`
  opts = opts || {};
  opts.path = opts.path || this.path();
  // set origins verification
  opts.allowRequest = opts.allowRequest || this.checkRequest.bind(this);

  var self = this;

  var connectPacket = { type: parser.CONNECT, nsp: '/' };
  this.encoder.encode(connectPacket, function (encodedPacket){
    // the CONNECT packet will be merged with Engine.IO handshake,
    // to reduce the number of round trips
    opts.initialPacket = encodedPacket;

    // initialize engine
    debug('creating engine.io instance with opts %j', opts);
    self.eio = engine.attach(srv, opts);

    // attach static file serving
    if (self._serveClient) self.attachServe(srv);

    // Export http server
    self.httpServer = srv;

    // bind to engine events
    self.bind(self.eio);
  });

  return this;
};

/**
 * Attaches the static file serving.
 *
 * @param {Function|http.Server} srv http server
 * @api private
 */

Server.prototype.attachServe = function(srv){
  debug('attaching client serving req handler');
  var url = this._path + '/socket.io.js';
  var urlMap = this._path + '/socket.io.js.map';
  var evs = srv.listeners('request').slice(0);
  var self = this;
  srv.removeAllListeners('request');
  srv.on('request', function(req, res) {
    if (0 === req.url.indexOf(urlMap)) {
      self.serveMap(req, res);
    } else if (0 === req.url.indexOf(url)) {
      self.serve(req, res);
    } else {
      for (var i = 0; i < evs.length; i++) {
        evs[i].call(srv, req, res);
      }
    }
  });
};

/**
 * Handles a request serving `/socket.io.js`
 *
 * @param {http.Request} req
 * @param {http.Response} res
 * @api private
 */

Server.prototype.serve = function(req, res){
  // Per the standard, ETags must be quoted:
  // https://tools.ietf.org/html/rfc7232#section-2.3
  var expectedEtag = '"' + clientVersion + '"';

  var etag = req.headers['if-none-match'];
  if (etag) {
    if (expectedEtag == etag) {
      debug('serve client 304');
      res.writeHead(304);
      res.end();
      return;
    }
  }

  debug('serve client source');
  res.setHeader('Content-Type', 'application/javascript');
  res.setHeader('ETag', expectedEtag);
  res.setHeader('X-SourceMap', 'socket.io.js.map');
  res.writeHead(200);
  res.end(clientSource);
};

/**
 * Handles a request serving `/socket.io.js.map`
 *
 * @param {http.Request} req
 * @param {http.Response} res
 * @api private
 */

Server.prototype.serveMap = function(req, res){
  // Per the standard, ETags must be quoted:
  // https://tools.ietf.org/html/rfc7232#section-2.3
  var expectedEtag = '"' + clientVersion + '"';

  var etag = req.headers['if-none-match'];
  if (etag) {
    if (expectedEtag == etag) {
      debug('serve client 304');
      res.writeHead(304);
      res.end();
      return;
    }
  }

  debug('serve client sourcemap');
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('ETag', expectedEtag);
  res.writeHead(200);
  res.end(clientSourceMap);
};

/**
 * Binds socket.io to an engine.io instance.
 *
 * @param {engine.Server} engine engine.io (or compatible) server
 * @return {Server} self
 * @api public
 */

Server.prototype.bind = function(engine){
  this.engine = engine;
  this.engine.on('connection', this.onconnection.bind(this));
  return this;
};

/**
 * Called with each incoming transport connection.
 *
 * @param {engine.Socket} conn
 * @return {Server} self
 * @api public
 */

Server.prototype.onconnection = function(conn){
  debug('incoming connection with id %s', conn.id);
  var client = new Client(this, conn);
  client.connect('/');
  return this;
};

/**
 * Looks up a namespace.
 *
 * @param {String} name nsp name
 * @param {Function} [fn] optional, nsp `connection` ev handler
 * @api public
 */

Server.prototype.of = function(name, fn){
  if (String(name)[0] !== '/') name = '/' + name;

  var nsp = this.nsps[name];
  if (!nsp) {
    debug('initializing namespace %s', name);
    nsp = new Namespace(this, name);
    this.nsps[name] = nsp;
  }
  if (fn) nsp.on('connect', fn);
  return nsp;
};

/**
 * Closes server connection
 *
 * @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed
 * @api public
 */

Server.prototype.close = function(fn){
  for (var id in this.nsps['/'].sockets) {
    if (this.nsps['/'].sockets.hasOwnProperty(id)) {
      this.nsps['/'].sockets[id].onclose();
    }
  }

  this.engine.close();

  if (this.httpServer) {
    this.httpServer.close(fn);
  } else {
    fn && fn();
  }
};

/**
 * Expose main namespace (/).
 */

var emitterMethods = Object.keys(Emitter.prototype).filter(function(key){
  return typeof Emitter.prototype[key] === 'function';
});

emitterMethods.concat(['to', 'in', 'use', 'send', 'write', 'clients', 'compress']).forEach(function(fn){
  Server.prototype[fn] = function(){
    return this.sockets[fn].apply(this.sockets, arguments);
  };
});

Namespace.flags.forEach(function(flag){
  Object.defineProperty(Server.prototype, flag, {
    get: function() {
      this.sockets.flags = this.sockets.flags || {};
      this.sockets.flags[flag] = true;
      return this;
    }
  });
});

/**
 * BC with `io.listen`
 */

Server.listen = Server;
<commit_msg>[fix] Update path of client file (#2934)<commit_after>
/**
 * Module dependencies.
 */

var http = require('http');
var read = require('fs').readFileSync;
var path = require('path');
var exists = require('fs').existsSync;
var engine = require('engine.io');
var client = require('socket.io-client');
var clientVersion = require('socket.io-client/package').version;
var Client = require('./client');
var Emitter = require('events').EventEmitter;
var Namespace = require('./namespace');
var Adapter = require('socket.io-adapter');
var parser = require('socket.io-parser');
var debug = require('debug')('socket.io:server');
var url = require('url');

/**
 * Module exports.
 */

module.exports = Server;

/**
 * Socket.IO client source.
 */

var clientSource = undefined;
var clientSourceMap = undefined;

/**
 * Server constructor.
 *
 * @param {http.Server|Number|Object} srv http server, port or options
 * @param {Object} [opts]
 * @api public
 */

function Server(srv, opts){
  if (!(this instanceof Server)) return new Server(srv, opts);
  if ('object' == typeof srv && srv instanceof Object && !srv.listen) {
    opts = srv;
    srv = null;
  }
  opts = opts || {};
  this.nsps = {};
  this.path(opts.path || '/socket.io');
  this.serveClient(false !== opts.serveClient);
  this.parser = opts.parser || parser;
  this.encoder = new this.parser.Encoder();
  this.adapter(opts.adapter || Adapter);
  this.origins(opts.origins || '*:*');
  this.sockets = this.of('/');
  if (srv) this.attach(srv, opts);
}

/**
 * Server request verification function, that checks for allowed origins
 *
 * @param {http.IncomingMessage} req request
 * @param {Function} fn callback to be called with the result: `fn(err, success)`
 */

Server.prototype.checkRequest = function(req, fn) {
  var origin = req.headers.origin || req.headers.referer;

  // file:// URLs produce a null Origin which can't be authorized via echo-back
  if ('null' == origin || null == origin) origin = '*';

  if (!!origin && typeof(this._origins) == 'function') return this._origins(origin, fn);
  if (this._origins.indexOf('*:*') !== -1) return fn(null, true);
  if (origin) {
    try {
      var parts = url.parse(origin);
      var defaultPort = 'https:' == parts.protocol ? 443 : 80;
      parts.port = parts.port != null
        ? parts.port
        : defaultPort;
      var ok =
        ~this._origins.indexOf(parts.hostname + ':' + parts.port) ||
        ~this._origins.indexOf(parts.hostname + ':*') ||
        ~this._origins.indexOf('*:' + parts.port);
      return fn(null, !!ok);
    } catch (ex) {
    }
  }
  fn(null, false);
};

/**
 * Sets/gets whether client code is being served.
 *
 * @param {Boolean} v whether to serve client code
 * @return {Server|Boolean} self when setting or value when getting
 * @api public
 */

Server.prototype.serveClient = function(v){
  if (!arguments.length) return this._serveClient;
  this._serveClient = v;
  var resolvePath = function(file){
    var filepath = path.resolve(__dirname, './../../', file);
    if (exists(filepath)) {
      return filepath;
    }
    return require.resolve(file);
  };
  if (v && !clientSource) {
    clientSource = read(resolvePath( 'socket.io-client/dist/socket.io.js'), 'utf-8');
    try {
      clientSourceMap = read(resolvePath( 'socket.io-client/dist/socket.io.js.map'), 'utf-8');
    } catch(err) {
      debug('could not load sourcemap file');
    }
  }
  return this;
};

/**
 * Old settings for backwards compatibility
 */

var oldSettings = {
  "transports": "transports",
  "heartbeat timeout": "pingTimeout",
  "heartbeat interval": "pingInterval",
  "destroy buffer size": "maxHttpBufferSize"
};

/**
 * Backwards compatibility.
 *
 * @api public
 */

Server.prototype.set = function(key, val){
  if ('authorization' == key && val) {
    this.use(function(socket, next) {
      val(socket.request, function(err, authorized) {
        if (err) return next(new Error(err));
        if (!authorized) return next(new Error('Not authorized'));
        next();
      });
    });
  } else if ('origins' == key && val) {
    this.origins(val);
  } else if ('resource' == key) {
    this.path(val);
  } else if (oldSettings[key] && this.eio[oldSettings[key]]) {
    this.eio[oldSettings[key]] = val;
  } else {
    console.error('Option %s is not valid. Please refer to the README.', key);
  }

  return this;
};

/**
 * Sets the client serving path.
 *
 * @param {String} v pathname
 * @return {Server|String} self when setting or value when getting
 * @api public
 */

Server.prototype.path = function(v){
  if (!arguments.length) return this._path;
  this._path = v.replace(/\/$/, '');
  return this;
};

/**
 * Sets the adapter for rooms.
 *
 * @param {Adapter} v pathname
 * @return {Server|Adapter} self when setting or value when getting
 * @api public
 */

Server.prototype.adapter = function(v){
  if (!arguments.length) return this._adapter;
  this._adapter = v;
  for (var i in this.nsps) {
    if (this.nsps.hasOwnProperty(i)) {
      this.nsps[i].initAdapter();
    }
  }
  return this;
};

/**
 * Sets the allowed origins for requests.
 *
 * @param {String} v origins
 * @return {Server|Adapter} self when setting or value when getting
 * @api public
 */

Server.prototype.origins = function(v){
  if (!arguments.length) return this._origins;

  this._origins = v;
  return this;
};

/**
 * Attaches socket.io to a server or port.
 *
 * @param {http.Server|Number} server or port
 * @param {Object} options passed to engine.io
 * @return {Server} self
 * @api public
 */

Server.prototype.listen =
Server.prototype.attach = function(srv, opts){
  if ('function' == typeof srv) {
    var msg = 'You are trying to attach socket.io to an express ' +
    'request handler function. Please pass a http.Server instance.';
    throw new Error(msg);
  }

  // handle a port as a string
  if (Number(srv) == srv) {
    srv = Number(srv);
  }

  if ('number' == typeof srv) {
    debug('creating http server and binding to %d', srv);
    var port = srv;
    srv = http.Server(function(req, res){
      res.writeHead(404);
      res.end();
    });
    srv.listen(port);

  }

  // set engine.io path to `/socket.io`
  opts = opts || {};
  opts.path = opts.path || this.path();
  // set origins verification
  opts.allowRequest = opts.allowRequest || this.checkRequest.bind(this);

  var self = this;

  var connectPacket = { type: parser.CONNECT, nsp: '/' };
  this.encoder.encode(connectPacket, function (encodedPacket){
    // the CONNECT packet will be merged with Engine.IO handshake,
    // to reduce the number of round trips
    opts.initialPacket = encodedPacket;

    // initialize engine
    debug('creating engine.io instance with opts %j', opts);
    self.eio = engine.attach(srv, opts);

    // attach static file serving
    if (self._serveClient) self.attachServe(srv);

    // Export http server
    self.httpServer = srv;

    // bind to engine events
    self.bind(self.eio);
  });

  return this;
};

/**
 * Attaches the static file serving.
 *
 * @param {Function|http.Server} srv http server
 * @api private
 */

Server.prototype.attachServe = function(srv){
  debug('attaching client serving req handler');
  var url = this._path + '/socket.io.js';
  var urlMap = this._path + '/socket.io.js.map';
  var evs = srv.listeners('request').slice(0);
  var self = this;
  srv.removeAllListeners('request');
  srv.on('request', function(req, res) {
    if (0 === req.url.indexOf(urlMap)) {
      self.serveMap(req, res);
    } else if (0 === req.url.indexOf(url)) {
      self.serve(req, res);
    } else {
      for (var i = 0; i < evs.length; i++) {
        evs[i].call(srv, req, res);
      }
    }
  });
};

/**
 * Handles a request serving `/socket.io.js`
 *
 * @param {http.Request} req
 * @param {http.Response} res
 * @api private
 */

Server.prototype.serve = function(req, res){
  // Per the standard, ETags must be quoted:
  // https://tools.ietf.org/html/rfc7232#section-2.3
  var expectedEtag = '"' + clientVersion + '"';

  var etag = req.headers['if-none-match'];
  if (etag) {
    if (expectedEtag == etag) {
      debug('serve client 304');
      res.writeHead(304);
      res.end();
      return;
    }
  }

  debug('serve client source');
  res.setHeader('Content-Type', 'application/javascript');
  res.setHeader('ETag', expectedEtag);
  res.writeHead(200);
  res.end(clientSource);
};

/**
 * Handles a request serving `/socket.io.js.map`
 *
 * @param {http.Request} req
 * @param {http.Response} res
 * @api private
 */

Server.prototype.serveMap = function(req, res){
  // Per the standard, ETags must be quoted:
  // https://tools.ietf.org/html/rfc7232#section-2.3
  var expectedEtag = '"' + clientVersion + '"';

  var etag = req.headers['if-none-match'];
  if (etag) {
    if (expectedEtag == etag) {
      debug('serve client 304');
      res.writeHead(304);
      res.end();
      return;
    }
  }

  debug('serve client sourcemap');
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('ETag', expectedEtag);
  res.writeHead(200);
  res.end(clientSourceMap);
};

/**
 * Binds socket.io to an engine.io instance.
 *
 * @param {engine.Server} engine engine.io (or compatible) server
 * @return {Server} self
 * @api public
 */

Server.prototype.bind = function(engine){
  this.engine = engine;
  this.engine.on('connection', this.onconnection.bind(this));
  return this;
};

/**
 * Called with each incoming transport connection.
 *
 * @param {engine.Socket} conn
 * @return {Server} self
 * @api public
 */

Server.prototype.onconnection = function(conn){
  debug('incoming connection with id %s', conn.id);
  var client = new Client(this, conn);
  client.connect('/');
  return this;
};

/**
 * Looks up a namespace.
 *
 * @param {String} name nsp name
 * @param {Function} [fn] optional, nsp `connection` ev handler
 * @api public
 */

Server.prototype.of = function(name, fn){
  if (String(name)[0] !== '/') name = '/' + name;

  var nsp = this.nsps[name];
  if (!nsp) {
    debug('initializing namespace %s', name);
    nsp = new Namespace(this, name);
    this.nsps[name] = nsp;
  }
  if (fn) nsp.on('connect', fn);
  return nsp;
};

/**
 * Closes server connection
 *
 * @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed
 * @api public
 */

Server.prototype.close = function(fn){
  for (var id in this.nsps['/'].sockets) {
    if (this.nsps['/'].sockets.hasOwnProperty(id)) {
      this.nsps['/'].sockets[id].onclose();
    }
  }

  this.engine.close();

  if (this.httpServer) {
    this.httpServer.close(fn);
  } else {
    fn && fn();
  }
};

/**
 * Expose main namespace (/).
 */

var emitterMethods = Object.keys(Emitter.prototype).filter(function(key){
  return typeof Emitter.prototype[key] === 'function';
});

emitterMethods.concat(['to', 'in', 'use', 'send', 'write', 'clients', 'compress']).forEach(function(fn){
  Server.prototype[fn] = function(){
    return this.sockets[fn].apply(this.sockets, arguments);
  };
});

Namespace.flags.forEach(function(flag){
  Object.defineProperty(Server.prototype, flag, {
    get: function() {
      this.sockets.flags = this.sockets.flags || {};
      this.sockets.flags[flag] = true;
      return this;
    }
  });
});

/**
 * BC with `io.listen`
 */

Server.listen = Server;
<|endoftext|>


<commit_before>var scan = require('./polyfill-scan'),
    reduce = require('./polyfill-reduce'),
    wrap = require('./polyfill-wrap'),
    code = require('./polyfill-code');

/**
 *
 * @param {Object}   options
 * @param {String}   [options.code]
 * @param {String[]} [options.browsers] Autoprefixer style list of browsers
 *
 * @example
 *
 * new AutoPolyFiller({
 *     browsers: ['IE 11', 'Chrome >= 31']
 * })
 * .add('"".trim();Object.create();new Promise()')
 * .polyfills;
 * // ['Promise']
 */
function AutoPolyFiller(options) {
    this.browsers = options.browsers;
    this.polyfills = [];
}

AutoPolyFiller.prototype = {
    /**
     * @param {String} code
     * @returns {String[]}
     * @private
     */
    _scan: function (code) {
        var polyfills = scan(code);

        // Do not reduce if no browsers
        if (this.browsers && this.browsers.length === 0) {
            return polyfills;
        }
        return reduce(polyfills, this.browsers);
    },

    _scanForPolyfillsOfPolyfills: function (polyfills) {
        var hasIterated = {};

        var iteratePolyfills = function (polyfills, polyfillName) {
            // Already scanned this polyfill
            if (hasIterated.hasOwnProperty(polyfillName)) {
                return polyfills;
            }
            hasIterated[polyfillName] = true;

            polyfills = polyfills.concat(this._scan(code(polyfillName)));

            return polyfills.concat(polyfills.reduce(iteratePolyfills, []));
        }.bind(this);

        return polyfills.reduce(iteratePolyfills, []);
    },

    /**
     *
     * @param {String} code
     * @returns {AutoPolyFiller}
     */
    add: function (code) {
        var polyfills = this._scan(code),
            polyfillsOfPolyfills = this._scanForPolyfillsOfPolyfills(polyfills);

        this.polyfills = this.polyfills
            .concat(polyfills)
            .concat(polyfillsOfPolyfills)
            // Make unique polyfills
            .reduce(function (polyfills, polyfill) {
                if (polyfills.indexOf(polyfill) === -1) {
                    polyfills.push(polyfill);
                }
                return polyfills;
            }, []);

        return this;
    },

    /**
     *
     * @returns {string} code that polyfills all listed functions
     */
    toString: function () {
        return this.polyfills.map(function (polyfillName) {
            var polyfillCode = code(polyfillName);
            return wrap(polyfillCode, polyfillName);
        }).join('');
    }
};

module.exports = function () {
    var browsers = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];

    if (browsers.length === 1 && browsers[0] instanceof Array) {
        browsers = browsers[0];
    }

    return new AutoPolyFiller({
        browsers: browsers
    });
};

/**
 *
 * @param {Object}   config
 * @param {Function} [config.test]
 * @param {Object}   [config.support]
 * @param {Object}   [config.polyfill]
 * @param {Object}   [config.wrapper]
 */
module.exports.use = function (config) {
    if (config.test) {
        scan.use({
            test: config.test
        });
    }

    if (config.support) {
        reduce.support(config.support);
    }

    if (config.polyfill) {
        code.addSource(config.polyfill);
    }

    if (config.wrapper) {
        wrap.addWrapper(config.wrapper);
    }
};
<commit_msg>jsdoc update<commit_after>var scan = require('./polyfill-scan'),
    reduce = require('./polyfill-reduce'),
    wrap = require('./polyfill-wrap'),
    code = require('./polyfill-code');

/**
 *
 * @param {Object}   options
 * @param {String[]} [options.browsers] Autoprefixer style list of browsers
 * @constructor
 *
 * @example
 *
 * new AutoPolyFiller({
 *     browsers: ['IE 11', 'Chrome >= 31']
 * })
 * .add('"".trim();Object.create();new Promise()')
 * .polyfills;
 * // ['Promise']
 */
function AutoPolyFiller(options) {
    this.browsers = options.browsers;
    this.polyfills = [];
}

AutoPolyFiller.prototype = {
    /**
     * Scans `code` cor polyfills javascipt code
     *
     * @param {String} code
     * @returns {String[]}
     * @private
     */
    _scan: function (code) {
        var polyfills = scan(code);

        // Do not reduce if no browsers
        if (this.browsers && this.browsers.length === 0) {
            return polyfills;
        }
        return reduce(polyfills, this.browsers);
    },

    /**
     * Scans for polyfills in code of each polyfills
     *
     * @param {String[]} polyfills list of polyfills names
     * @returns {String[]} list contains non unique polyfills
     * @private
     */
    _scanForPolyfillsOfPolyfills: function (polyfills) {
        var hasIterated = {};

        var iteratePolyfills = function (polyfills, polyfillName) {
            // Already scanned this polyfill
            if (hasIterated.hasOwnProperty(polyfillName)) {
                return polyfills;
            }
            hasIterated[polyfillName] = true;

            polyfills = polyfills.concat(this._scan(code(polyfillName)));

            return polyfills.concat(polyfills.reduce(iteratePolyfills, []));
        }.bind(this);

        return polyfills.reduce(iteratePolyfills, []);
    },

    /**
     * Inspects given `code` for polyfills
     * @param {String} code javascipt code
     * @returns {AutoPolyFiller}
     */
    add: function (code) {
        var polyfills = this._scan(code),
            polyfillsOfPolyfills = this._scanForPolyfillsOfPolyfills(polyfills);

        this.polyfills = this.polyfills
            .concat(polyfills)
            .concat(polyfillsOfPolyfills)
            // Make unique polyfills
            .reduce(function (polyfills, polyfill) {
                if (polyfills.indexOf(polyfill) === -1) {
                    polyfills.push(polyfill);
                }
                return polyfills;
            }, []);

        return this;
    },

    /**
     *
     * @returns {string} code that polyfills all listed functions
     */
    toString: function () {
        return this.polyfills.map(function (polyfillName) {
            var polyfillCode = code(polyfillName);
            return wrap(polyfillCode, polyfillName);
        }).join('');
    }
};

/**
 * Polyfill interface
 *
 * @example
 *
 * polyfiller('IE 11', 'Chrome >= 31')
 * .add('"".trim();Object.create();new Promise()')
 * .polyfills;
 * // ['Promise']
 */
module.exports = function () {
    var browsers = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];

    if (browsers.length === 1 && browsers[0] instanceof Array) {
        browsers = browsers[0];
    }

    return new AutoPolyFiller({
        browsers: browsers
    });
};

/**
 * Customizes polyfills
 *
 * @param {Object}   config
 * @param {Function} [config.test]
 * @param {Object}   [config.support]
 * @param {Object}   [config.polyfill]
 * @param {Object}   [config.wrapper]
 */
module.exports.use = function (config) {
    if (config.test) {
        scan.use({
            test: config.test
        });
    }

    if (config.support) {
        reduce.support(config.support);
    }

    if (config.polyfill) {
        code.addSource(config.polyfill);
    }

    if (config.wrapper) {
        wrap.addWrapper(config.wrapper);
    }
};
<|endoftext|>


<commit_before>var Negotiator = require('negotiator');
var Hoek = require('hoek');
var Boom = require('boom');

exports.register = function (plugin,options,next) {

  var defaults = {
    mediaTypes: {
      'application/json': true,
      'text/plain': true,
    }
  };

  var config = Hoek.applyToDefaults(defaults, options);

  plugin.ext('onPreResponse', function (request, reply) {
    var requestSettings = request.route.settings.plugins['hapi-negotiator'];

    if (requestSettings === false) {
      return reply();
    }

    requestSettings = Hoek.applyToDefaults(config, requestSettings || {});
    var requestNegotiator = new Negotiator(request.raw.req);
    var selectedMediaType = requestNegotiator.mediaType(Object.keys(requestSettings.mediaTypes));
    var selectedOption = requestSettings.mediaTypes[selectedMediaType];

    if (!selectedOption) {
      reply(Boom.notAcceptable());
    }
    else if (selectedOption === true)
    {
      reply();
    }
    else if (typeof selectedOption === 'function')
    {
      selectedOption(request, reply);
    }
    else if (selectedOption.method)
    {
      selectedOption.args.push(request.response.source);
      reply[selectedOption.method].apply(reply, selectedOption.args);
    }
    else
    {
      // Not really sure I just reply or just let it fail
      // Log something??
      reply();
    }
  });

  next();
};

exports.register.attributes = {
  pkg: require('../package.json')
};<commit_msg>change ext continuation method from reply() to reply.continue()<commit_after>var Negotiator = require('negotiator');
var Hoek = require('hoek');
var Boom = require('boom');

exports.register = function (plugin,options,next) {

  var defaults = {
    mediaTypes: {
      'application/json': true,
      'text/plain': true,
    }
  };

  var config = Hoek.applyToDefaults(defaults, options);

  plugin.ext('onPreResponse', function (request, reply) {
    var requestSettings = request.route.settings.plugins['hapi-negotiator'];

    if (requestSettings === false) {
      return reply.continue();
    }

    requestSettings = Hoek.applyToDefaults(config, requestSettings || {});
    var requestNegotiator = new Negotiator(request.raw.req);
    var selectedMediaType = requestNegotiator.mediaType(Object.keys(requestSettings.mediaTypes));
    var selectedOption = requestSettings.mediaTypes[selectedMediaType];

    if (!selectedOption) {
      reply(Boom.notAcceptable());
    }
    else if (selectedOption === true)
    {
      reply.continue();
    }
    else if (typeof selectedOption === 'function')
    {
      selectedOption(request, reply);
    }
    else if (selectedOption.method)
    {
      selectedOption.args.push(request.response.source);
      reply[selectedOption.method].apply(reply, selectedOption.args);
    }
    else
    {
      // Not really sure I just reply or just let it fail
      // Log something??
      reply.continue();
    }
  });

  next();
};

exports.register.attributes = {
  pkg: require('../package.json')
};<|endoftext|>


<commit_before>var aws4_sign = require("aws4-signature");
var clone = require("clone");
var Joi = require("joi");
var url_template = require("url-template");

var s3_host = url_template.parse("https://{bucket}.s3.amazonaws.com");
var s3_regions = [
  "ap-northeast-1",
  "ap-southeast-1",
  "ap-southeast-2",
  "eu-central-1",
  "eu-west-1",
  "sa-east-1",
  "us-east-1",
  "us-west-1",
  "us-west-2"
];
var valid_options = Joi.object().keys({
  id: Joi.string(),
  secret: Joi.string(),
  date: Joi.date(),
  region: Joi.string().valid(s3_regions),
  bucket: Joi.string(),
  policy: Joi.object().keys({
    expiration: Joi.date(),
    conditions: Joi.array()
  })
});

module.exports = function policy_gen(options) {
  // Validation options passed in
  var valid = Joi.validate(options, valid_options, {
    presence: "required"
  });

  if (valid.error) {
    throw valid.error;
  }

  // Convert the date to the format that AWS uses
  var date_time = new Date(options.date).toISOString().replace(/[:\-]|\.\d{3}/g, "");
  var date = date_time.substr(0, 8);

  // Generate policy
  var policy = clone(options.policy);
  policy.conditions.push({ "bucket": options.bucket });
  policy.conditions.push({ "x-amz-algorithm": "AWS4-HMAC-SHA256"});
  policy.conditions.push({
    "x-amz-credential": options.id + "/" + date + "/" + options.region + "/s3/aws4_request"
  });
  policy.conditions.push({ "x-amz-date": date_time });
  policy.expiration = new Date(policy.expiration).toISOString();

  var base64_policy = new Buffer(JSON.stringify(policy)).toString("base64");
  var signature = aws4_sign(options.secret, options.date, options.region, "s3", base64_policy);

  var output = {
    fields: {},
    host: s3_host.expand({
      bucket: options.bucket
    }),
    starts_with: []
  };

  policy.conditions.forEach(function(p) {
    if (Array.isArray(p)) {
      if (p[0] === "starts-with") {
        output.starts_with.push(p[1].substr(1));
      }
      output.fields[p[1].substr(1)] = p[2];
    } else {
      var key = Object.keys(p)[0];
      output.fields[key] = p[key];
    }
  });
  output.fields.policy = base64_policy;
  output.fields["x-amz-signature"] = signature;

  return output;
};
<commit_msg>add ap-northeast-2 region<commit_after>var aws4_sign = require("aws4-signature");
var clone = require("clone");
var Joi = require("joi");
var url_template = require("url-template");

var s3_host = url_template.parse("https://{bucket}.s3.amazonaws.com");
var s3_regions = [
  "ap-northeast-1",
  "ap-northeast-2",
  "ap-southeast-1",
  "ap-southeast-2",
  "eu-central-1",
  "eu-west-1",
  "sa-east-1",
  "us-east-1",
  "us-west-1",
  "us-west-2"
];
var valid_options = Joi.object().keys({
  id: Joi.string(),
  secret: Joi.string(),
  date: Joi.date(),
  region: Joi.string().valid(s3_regions),
  bucket: Joi.string(),
  policy: Joi.object().keys({
    expiration: Joi.date(),
    conditions: Joi.array()
  })
});

module.exports = function policy_gen(options) {
  // Validation options passed in
  var valid = Joi.validate(options, valid_options, {
    presence: "required"
  });

  if (valid.error) {
    throw valid.error;
  }

  // Convert the date to the format that AWS uses
  var date_time = new Date(options.date).toISOString().replace(/[:\-]|\.\d{3}/g, "");
  var date = date_time.substr(0, 8);

  // Generate policy
  var policy = clone(options.policy);
  policy.conditions.push({ "bucket": options.bucket });
  policy.conditions.push({ "x-amz-algorithm": "AWS4-HMAC-SHA256"});
  policy.conditions.push({
    "x-amz-credential": options.id + "/" + date + "/" + options.region + "/s3/aws4_request"
  });
  policy.conditions.push({ "x-amz-date": date_time });
  policy.expiration = new Date(policy.expiration).toISOString();

  var base64_policy = new Buffer(JSON.stringify(policy)).toString("base64");
  var signature = aws4_sign(options.secret, options.date, options.region, "s3", base64_policy);

  var output = {
    fields: {},
    host: s3_host.expand({
      bucket: options.bucket
    }),
    starts_with: []
  };

  policy.conditions.forEach(function(p) {
    if (Array.isArray(p)) {
      if (p[0] === "starts-with") {
        output.starts_with.push(p[1].substr(1));
      }
      output.fields[p[1].substr(1)] = p[2];
    } else {
      var key = Object.keys(p)[0];
      output.fields[key] = p[key];
    }
  });
  output.fields.policy = base64_policy;
  output.fields["x-amz-signature"] = signature;

  return output;
};
<|endoftext|>