<commit_before>'use strict';

import path from 'path';
import fs from 'fs-extra';
import glob from 'glob';
import rl from 'readline';
import 'babel-polyfill';
const async = require('async');
const yaml = require('js-yaml');
const temp = require('temp').track();
const pathExists = require('path-exists');

export default class I18nPatch {
  constructor(src, options) {
    if (!src) {
      throw new Error('src is required');
    }
    this.src = src;
    this.options = options || {};
    this.options.dest = this.options.dest || this.src;
    this.options.config = this.options.config || 'config';
  }

  generate(config, localeConfig) {
    return new Promise((resolve, reject) => {
      this.setConfigs(config, localeConfig);
      this.buildPatterns();
      if (this.hasDest()) {
        fs.copySync(this.src, this.options.dest);
      }

      async.waterfall(this.config.translations.map((t) => {
        return (cb) => {
          this.processTranslation(t)
          .catch((err) => cb(err))
          .then(() => cb());
        };
      }), (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
  }

  hasDest() {
    return this.src !== this.options.dest;
  }

  setConfigs(config, localeConfig) {
    this.config = config || this.readConfigFile('i18n');
    if (localeConfig) {
      this.localeConfig = localeConfig;
    } else {
      if (!this.options.locale) {
        throw new Error('Could not determine locale');
      }
      this.localeConfig = this.readConfigFile(this.options.locale);
    }
  }

  readConfigFile(name) {
    let configPath = path.join(this.options.config, `${name}.yml`);
    if (pathExists.sync(configPath)) {
      try {
        return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'));
      } catch (err) {
        console.log(`Cannot read ${configPath}`);
        console.log(err.stack);
        process.exit(1);
      }
    } else {
      configPath = path.join(this.options.config, `${name}.json`);
      try {
        return JSON.parse(fs.readFileSync(configPath));
      } catch (err) {
        console.log(`Cannot read ${configPath}`);
        console.log(err.stack);
        process.exit(1);
      }
    }
  }

  buildPatterns() {
    for (let t of this.config.translations) {
      if (t.conditionals) {
        for (let c of t.conditionals) {
          if (!c.insert || !this.localeConfig.hasOwnProperty(c.insert.value)) {
            continue;
          }
          c.insert.resolved = this.localeConfig[c.insert.value];
          if (c.insert.resolved && !c.insert.resolved.endsWith('\n')) {
            c.insert.resolved += '\n';
          }
        }
      }
      for (let p of t.patterns) {
        this.resolve(p);
        if (p.insert && this.localeConfig.hasOwnProperty(p.insert.value)) {
          p.insert.resolved = this.localeConfig[p.insert.value];
          if (p.insert.resolved && !p.insert.resolved.endsWith('\n')) {
            p.insert.resolved += '\n';
          }
        }
      }
    }
  }

  processTranslation(t) {
    return new Promise((resolve, reject) => {
      let srcGlob = t.src || '**/*';
      let srcPaths = path.join(this.options.dest, srcGlob);
      glob(srcPaths, null, (err, files) => {
        if (err) {
          reject(err);
          return;
        }
        async.each(files, (file, cb) => {
          this.processFile(t, file)
          .catch((err) => cb(err))
          .then(() => cb());
        }, (err) => {
          if (err) {
            reject(err);
          } else {
            resolve();
          }
        });
      });
    });
  }

  processFile(t, file) {
    return new Promise((resolve, reject) => {
      this.processFilePerLine(t, file)
      .catch((err) => reject(err))
      .then((file) => {
        if (this.hasPerFilePattern(t)) {
          this.processFilePerFile(t, file)
          .catch((err) => reject(err))
          .then((file) => resolve(file));
        } else {
          resolve(file);
        }
      });
    });
  }

  processFilePerLine(t, file) {
    return new Promise((resolve, reject) => {
      // Per-line processing
      let matched = false;
      let beginBuffer = [];
      let endBuffer = [];
      let error;
      let lr = rl.createInterface({
        input: fs.createReadStream(file)
      });
      let out = temp.createWriteStream()
      .on('error', (err) => {
        reject(err);
      })
      .on('close', () => {
        if (error) {
          // This can be set in 'error' callback of lr
          return;
        }
        if (matched) {
          // TODO Preserve original file stats
          fs.copySync(out.path, file);

          if (1 <= beginBuffer.length) {
            let value = '';
            for (let e of beginBuffer) {
              value += e;
              if (!e.endsWith('\n')) {
                value += '\n';
              }
            }
            let content = fs.readFileSync(file, 'utf8');
            fs.writeFileSync(file, value + content, 'utf8');
          }
          if (1 <= endBuffer.length) {
            let value = '';
            for (let e of endBuffer) {
              value += e;
              if (!e.endsWith('\n')) {
                value += '\n';
              }
            }
            let content = fs.readFileSync(file, 'utf8');
            if (!content.endsWith('\n')) {
              content += '\n';
            }
            fs.writeFileSync(file, content + value, 'utf8');
          }
        }
        resolve(file);
      });
      lr.on('line', (line) => {
        let result = line;
        for (let p of t.patterns) {
          if (!p.resolved) {
            continue;
          }
          let before = result;
          let resolved = p.resolved;
          if (p.args) {
            // TODO apply args to resolved recursively
            for (let i = 0; i < p.args.length; i++) {
              let argResolved = p.argsResolved[i];
              if (argResolved) {
                if (argResolved.replace && typeof argResolved.replace !== 'function') {
                  if (argResolved.resolved) {
                    if (argResolved.args) {
                      for (let j = 0; j < argResolved.args.length; j++) {
                        let argResolvedArgResolved = argResolved.argsResolved[j];
                        if (argResolvedArgResolved) {
                          argResolved.resolved = argResolved.resolved.replace(`{${j}}`, argResolvedArgResolved);
                        } else {
                          argResolved.resolved = argResolved.resolved.replace(`{${j}}`, argResolved.args[j]);
                        }
                      }
                    }
                    resolved = resolved.replace(`{${i}}`, argResolved.resolved);
                  } else {
                    resolved = resolved.replace(`{${i}}`, argResolved.replace);
                  }
                } else {
                  resolved = resolved.replace(`{${i}}`, argResolved);
                }
              } else {
                resolved = resolved.replace(`{${i}}`, p.args[i]);
              }
            }
          }
          result = result.replace(p.pattern, resolved);
          if (p.insert && p.insert.resolved) {
            if (p.insert.at === 'begin') {
              if (beginBuffer.indexOf(p.insert.resolved) < 0) {
                beginBuffer.push(p.insert.resolved);
              }
            } else if (p.insert.at === 'end') {
              if (endBuffer.indexOf(p.insert.resolved) < 0) {
                endBuffer.push(p.insert.resolved);
              }
            }
          }
          if (before === result) {
            continue;
          }
          matched = true;
          if (t.conditionals) {
            for (let c of t.conditionals) {
              if (!c.insert || !c.insert.resolved) {
                continue;
              }
              if (c.insert.at === 'begin') {
                if (beginBuffer.indexOf(c.insert.resolved) < 0) {
                  beginBuffer.push(c.insert.resolved);
                }
              } else if (c.insert.at === 'end') {
                if (endBuffer.indexOf(c.insert.resolved) < 0) {
                  endBuffer.push(c.insert.resolved);
                }
              }
            }
          }
        }
        // TODO Preserve original newline if possible
        out.write(`${result}\n`);
      })
      .on('error', (err) => {
        error = err;
        out.end();
        reject(err);
      })
      .on('close', () => {
        out.end();
      });
    });
  }

  processFilePerFile(t, file) {
    return new Promise((resolve, reject) => {
      try {
        for (let p of t.patterns) {
          if (p.pattern || !p.insert || !p.insert.resolved) {
            continue;
          }
          let at = p.insert.at;
          let value = p.insert.resolved;
          if (!value.endsWith('\n')) {
            value += '\n';
          }
          if (at === 'begin') {
            let content = fs.readFileSync(file, 'utf8');
            fs.writeFileSync(file, value + content, 'utf8');
          } else if (at === 'end') {
            let content = fs.readFileSync(file, 'utf8');
            if (!content.endsWith('\n')) {
              content += '\n';
            }
            fs.writeFileSync(file, content + value, 'utf8');
          }
        }
        resolve();
      } catch (err) {
        reject(err);
      }
    });
  }

  hasPerFilePattern(t) {
    return !!t.patterns.find(p => p.insert);
  }

  resolve(obj) {
    if (!obj.replace) {
      return;
    }

    let resolved = false;
    obj.resolved = obj.replace.replace(/\${([^}]*)}/g, (all, matched) => {
      if (this.localeConfig.hasOwnProperty(matched)) {
        resolved = true;
      }
      return this.localeConfig[matched];
    });
    if (!resolved) {
      obj.resolved = undefined;
    }

    if (obj.args) {
      obj.argsResolved = [];
      for (let i = 0; i < obj.args.length; i++) {
        let argResolved = false;
        let a = obj.args[i];
        if (a.replace && typeof a.replace !== 'function') {
          this.resolve(a);
          obj.argsResolved.push(a);
        } else if (a) {
          obj.argsResolved.push(a.replace(/\${([^}]*)}/g, (all, matched) => {
            if (this.localeConfig.hasOwnProperty(matched)) {
              argResolved = true;
            }
            return this.localeConfig[matched];
          }));
          if (!argResolved) {
            obj.argsResolved[i] = undefined;
          }
        }
      }
    }
  }
}
<commit_msg>Resolve args recursively<commit_after>'use strict';

import path from 'path';
import fs from 'fs-extra';
import glob from 'glob';
import rl from 'readline';
import 'babel-polyfill';
const async = require('async');
const yaml = require('js-yaml');
const temp = require('temp').track();
const pathExists = require('path-exists');

export default class I18nPatch {
  constructor(src, options) {
    if (!src) {
      throw new Error('src is required');
    }
    this.src = src;
    this.options = options || {};
    this.options.dest = this.options.dest || this.src;
    this.options.config = this.options.config || 'config';
  }

  generate(config, localeConfig) {
    return new Promise((resolve, reject) => {
      this.setConfigs(config, localeConfig);
      this.buildPatterns();
      if (this.hasDest()) {
        fs.copySync(this.src, this.options.dest);
      }

      async.waterfall(this.config.translations.map((t) => {
        return (cb) => {
          this.processTranslation(t)
          .catch((err) => cb(err))
          .then(() => cb());
        };
      }), (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
  }

  hasDest() {
    return this.src !== this.options.dest;
  }

  setConfigs(config, localeConfig) {
    this.config = config || this.readConfigFile('i18n');
    if (localeConfig) {
      this.localeConfig = localeConfig;
    } else {
      if (!this.options.locale) {
        throw new Error('Could not determine locale');
      }
      this.localeConfig = this.readConfigFile(this.options.locale);
    }
  }

  readConfigFile(name) {
    let configPath = path.join(this.options.config, `${name}.yml`);
    if (pathExists.sync(configPath)) {
      try {
        return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'));
      } catch (err) {
        console.log(`Cannot read ${configPath}`);
        console.log(err.stack);
        process.exit(1);
      }
    } else {
      configPath = path.join(this.options.config, `${name}.json`);
      try {
        return JSON.parse(fs.readFileSync(configPath));
      } catch (err) {
        console.log(`Cannot read ${configPath}`);
        console.log(err.stack);
        process.exit(1);
      }
    }
  }

  buildPatterns() {
    for (let t of this.config.translations) {
      if (t.conditionals) {
        for (let c of t.conditionals) {
          if (!c.insert || !this.localeConfig.hasOwnProperty(c.insert.value)) {
            continue;
          }
          c.insert.resolved = this.localeConfig[c.insert.value];
          if (c.insert.resolved && !c.insert.resolved.endsWith('\n')) {
            c.insert.resolved += '\n';
          }
        }
      }
      for (let p of t.patterns) {
        this.resolve(p);
        if (p.insert && this.localeConfig.hasOwnProperty(p.insert.value)) {
          p.insert.resolved = this.localeConfig[p.insert.value];
          if (p.insert.resolved && !p.insert.resolved.endsWith('\n')) {
            p.insert.resolved += '\n';
          }
        }
      }
    }
  }

  processTranslation(t) {
    return new Promise((resolve, reject) => {
      let srcGlob = t.src || '**/*';
      let srcPaths = path.join(this.options.dest, srcGlob);
      glob(srcPaths, null, (err, files) => {
        if (err) {
          reject(err);
          return;
        }
        async.each(files, (file, cb) => {
          this.processFile(t, file)
          .catch((err) => cb(err))
          .then(() => cb());
        }, (err) => {
          if (err) {
            reject(err);
          } else {
            resolve();
          }
        });
      });
    });
  }

  processFile(t, file) {
    return new Promise((resolve, reject) => {
      this.processFilePerLine(t, file)
      .catch((err) => reject(err))
      .then((file) => {
        if (this.hasPerFilePattern(t)) {
          this.processFilePerFile(t, file)
          .catch((err) => reject(err))
          .then((file) => resolve(file));
        } else {
          resolve(file);
        }
      });
    });
  }

  processFilePerLine(t, file) {
    return new Promise((resolve, reject) => {
      // Per-line processing
      let matched = false;
      let beginBuffer = [];
      let endBuffer = [];
      let error;
      let lr = rl.createInterface({
        input: fs.createReadStream(file)
      });
      let out = temp.createWriteStream()
      .on('error', (err) => {
        reject(err);
      })
      .on('close', () => {
        if (error) {
          // This can be set in 'error' callback of lr
          return;
        }
        if (matched) {
          // TODO Preserve original file stats
          fs.copySync(out.path, file);

          if (1 <= beginBuffer.length) {
            let value = '';
            for (let e of beginBuffer) {
              value += e;
              if (!e.endsWith('\n')) {
                value += '\n';
              }
            }
            let content = fs.readFileSync(file, 'utf8');
            fs.writeFileSync(file, value + content, 'utf8');
          }
          if (1 <= endBuffer.length) {
            let value = '';
            for (let e of endBuffer) {
              value += e;
              if (!e.endsWith('\n')) {
                value += '\n';
              }
            }
            let content = fs.readFileSync(file, 'utf8');
            if (!content.endsWith('\n')) {
              content += '\n';
            }
            fs.writeFileSync(file, content + value, 'utf8');
          }
        }
        resolve(file);
      });
      lr.on('line', (line) => {
        let result = line;
        for (let p of t.patterns) {
          if (!p.resolved) {
            continue;
          }
          let before = result;
          result = this.applyToResolved(result, p, p.pattern);
          if (p.insert && p.insert.resolved) {
            if (p.insert.at === 'begin') {
              if (beginBuffer.indexOf(p.insert.resolved) < 0) {
                beginBuffer.push(p.insert.resolved);
              }
            } else if (p.insert.at === 'end') {
              if (endBuffer.indexOf(p.insert.resolved) < 0) {
                endBuffer.push(p.insert.resolved);
              }
            }
          }
          if (before === result) {
            continue;
          }
          matched = true;
          if (t.conditionals) {
            for (let c of t.conditionals) {
              if (!c.insert || !c.insert.resolved) {
                continue;
              }
              if (c.insert.at === 'begin') {
                if (beginBuffer.indexOf(c.insert.resolved) < 0) {
                  beginBuffer.push(c.insert.resolved);
                }
              } else if (c.insert.at === 'end') {
                if (endBuffer.indexOf(c.insert.resolved) < 0) {
                  endBuffer.push(c.insert.resolved);
                }
              }
            }
          }
        }
        // TODO Preserve original newline if possible
        out.write(`${result}\n`);
      })
      .on('error', (err) => {
        error = err;
        out.end();
        reject(err);
      })
      .on('close', () => {
        out.end();
      });
    });
  }

  processFilePerFile(t, file) {
    return new Promise((resolve, reject) => {
      try {
        for (let p of t.patterns) {
          if (p.pattern || !p.insert || !p.insert.resolved) {
            continue;
          }
          let at = p.insert.at;
          let value = p.insert.resolved;
          if (!value.endsWith('\n')) {
            value += '\n';
          }
          if (at === 'begin') {
            let content = fs.readFileSync(file, 'utf8');
            fs.writeFileSync(file, value + content, 'utf8');
          } else if (at === 'end') {
            let content = fs.readFileSync(file, 'utf8');
            if (!content.endsWith('\n')) {
              content += '\n';
            }
            fs.writeFileSync(file, content + value, 'utf8');
          }
        }
        resolve();
      } catch (err) {
        reject(err);
      }
    });
  }

  hasPerFilePattern(t) {
    return !!t.patterns.find(p => p.insert);
  }

  resolve(obj) {
    if (!obj.replace) {
      return;
    }

    let resolved = false;
    obj.resolved = obj.replace.replace(/\${([^}]*)}/g, (all, matched) => {
      if (this.localeConfig.hasOwnProperty(matched)) {
        resolved = true;
      }
      return this.localeConfig[matched];
    });
    if (!resolved) {
      obj.resolved = undefined;
    }

    if (obj.args) {
      obj.argsResolved = [];
      for (let i = 0; i < obj.args.length; i++) {
        let argResolved = false;
        let a = obj.args[i];
        if (a.replace && typeof a.replace !== 'function') {
          this.resolve(a);
          obj.argsResolved.push(a);
        } else if (a) {
          obj.argsResolved.push(a.replace(/\${([^}]*)}/g, (all, matched) => {
            if (this.localeConfig.hasOwnProperty(matched)) {
              argResolved = true;
            }
            return this.localeConfig[matched];
          }));
          if (!argResolved) {
            obj.argsResolved[i] = undefined;
          }
        }
      }
    }
  }

  applyToResolved(target, obj, pattern) {
    let resolved = obj.resolved;
    if (obj.args) {
      for (let i = 0; i < obj.args.length; i++) {
        let argResolved = obj.argsResolved[i];
        if (argResolved) {
          if (argResolved.replace && typeof argResolved.replace !== 'function') {
            if (argResolved.resolved) {
              resolved = this.applyToArgResolved(resolved, argResolved, `{${i}}`);
            } else {
              resolved = resolved.replace(`{${i}}`, argResolved.replace);
            }
          } else {
            resolved = resolved.replace(`{${i}}`, argResolved);
          }
        } else {
          resolved = resolved.replace(`{${i}}`, obj.args[i]);
        }
      }
    }
    return target.replace(pattern, resolved);
  }

  applyToArgResolved(target, obj, pattern) {
    if (obj.args) {
      for (let i = 0; i < obj.args.length; i++) {
        let argResolved = obj.argsResolved[i];
        if (argResolved) {
          obj.resolved = this.applyToArgResolved(obj.resolved, argResolved, `{${i}}`);
        } else {
          obj.resolved = obj.resolved.replace(`{${i}}`, obj.args[i]);
        }
      }
    }
    return target.replace(pattern, obj.resolved);
  }
}
<|endoftext|>


<commit_before>import * as Babel from 'babel-core';

import {runScripts} from './transformScriptTags';

const isArray = Array.isArray || (arg => Object.prototype.toString.call(arg) === '[object Array]');

/**
 * Loads the given name (or [name, options] pair) from the given table object
 * holding the available presets or plugins.
 *
 * Returns undefined if the preset or plugin is not available; passes through
 * name unmodified if it (or the first element of the pair) is not a string.
 */
function loadBuiltin(builtinTable, name) {
  if (isArray(name) && typeof name[0] === 'string') {
    if (builtinTable.hasOwnProperty(name[0])) {
      return [builtinTable[name[0]]].concat(name.slice(1));
    }
    return;
  } else if (typeof name === 'string') {
    return builtinTable[name];
  }
  // Could be an actual preset/plugin module
  return name;
}

/**
 * Parses plugin names and presets from the specified options.
 */
function processOptions(options) {
  // Parse preset names
  const presets = (options.presets || []).map(presetName => {
    const preset = loadBuiltin(availablePresets, presetName);

    if (preset) {
      // workaround for babel issue
      // at some point, babel copies the preset, losing the non-enumerable
      // buildPreset key; convert it into an enumerable key.
      if (isArray(preset) && typeof preset[0] === 'object' && preset[0].hasOwnProperty('buildPreset')) {
        preset[0] = { ...preset[0], buildPreset: preset[0].buildPreset }
      }
    } else {
      throw new Error(`Invalid preset specified in Babel options: "${presetName}"`);
    }
    return preset;
  });

  // Parse plugin names
  const plugins = (options.plugins || []).map(pluginName => {
    const plugin = loadBuiltin(availablePlugins, pluginName);

    if (!plugin) {
      throw new Error(`Invalid plugin specified in Babel options: "${pluginName}"`);
    }
    return plugin;
  });

  return {
    babelrc: false,
    ...options,
    presets,
    plugins,
  }
}

export function transform(code, options) {
  return Babel.transform(code, processOptions(options));
}

export function transformFromAst(ast, code, options) {
  return Babel.transformFromAst(ast, code, processOptions(options));
}
export const availablePlugins = {};
export const availablePresets = {};

/**
 * Registers a named plugin for use with Babel.
 */
export function registerPlugin(name, plugin) {
  if (availablePlugins.hasOwnProperty(name)) {
    console.warn(`A plugin named "${name}" is already registered, it will be overridden`);
  }
  availablePlugins[name] = plugin;
}
/**
 * Registers multiple plugins for use with Babel. `newPlugins` should be an object where the key
 * is the name of the plugin, and the value is the plugin itself.
 */
export function registerPlugins(newPlugins) {
  Object.keys(newPlugins).forEach(name => registerPlugin(name, newPlugins[name]));
}

/**
 * Registers a named preset for use with Babel.
 */
export function registerPreset(name, preset) {
  if (availablePresets.hasOwnProperty(name)) {
    console.warn(`A preset named "${name}" is already registered, it will be overridden`);
  }
  availablePresets[name] = preset;
}
/**
 * Registers multiple presets for use with Babel. `newPresets` should be an object where the key
 * is the name of the preset, and the value is the preset itself.
 */
export function registerPresets(newPresets) {
  Object.keys(newPresets).forEach(name => registerPreset(name, newPresets[name]));
}

// All the plugins we should bundle
registerPlugins({
  'check-es2015-constants': require('babel-plugin-check-es2015-constants'),
  'external-helpers': require('babel-plugin-external-helpers'),
  'syntax-async-functions': require('babel-plugin-syntax-async-functions'),
  'syntax-async-generators': require('babel-plugin-syntax-async-generators'),
  'syntax-class-constructor-call': require('babel-plugin-syntax-class-constructor-call'),
  'syntax-class-properties': require('babel-plugin-syntax-class-properties'),
  'syntax-decorators': require('babel-plugin-syntax-decorators'),
  'syntax-do-expressions': require('babel-plugin-syntax-do-expressions'),
  'syntax-exponentiation-operator': require('babel-plugin-syntax-exponentiation-operator'),
  'syntax-export-extensions': require('babel-plugin-syntax-export-extensions'),
  'syntax-flow': require('babel-plugin-syntax-flow'),
  'syntax-function-bind': require('babel-plugin-syntax-function-bind'),
  'syntax-function-sent': require('babel-plugin-syntax-function-sent'),
  'syntax-jsx': require('babel-plugin-syntax-jsx'),
  'syntax-object-rest-spread': require('babel-plugin-syntax-object-rest-spread'),
  'syntax-trailing-function-commas': require('babel-plugin-syntax-trailing-function-commas'),
  'transform-async-functions': require('babel-plugin-transform-async-functions'),
  'transform-async-to-generator': require('babel-plugin-transform-async-to-generator'),
  'transform-async-to-module-method': require('babel-plugin-transform-async-to-module-method'),
  'transform-class-constructor-call': require('babel-plugin-transform-class-constructor-call'),
  'transform-class-properties': require('babel-plugin-transform-class-properties'),
  'transform-decorators': require('babel-plugin-transform-decorators'),
  'transform-decorators-legacy': require('babel-plugin-transform-decorators-legacy').default, // <- No clue. Nope.
  'transform-do-expressions': require('babel-plugin-transform-do-expressions'),
  'transform-es2015-arrow-functions': require('babel-plugin-transform-es2015-arrow-functions'),
  'transform-es2015-block-scoped-functions': require('babel-plugin-transform-es2015-block-scoped-functions'),
  'transform-es2015-block-scoping': require('babel-plugin-transform-es2015-block-scoping'),
  'transform-es2015-classes': require('babel-plugin-transform-es2015-classes'),
  'transform-es2015-computed-properties': require('babel-plugin-transform-es2015-computed-properties'),
  'transform-es2015-destructuring': require('babel-plugin-transform-es2015-destructuring'),
  'transform-es2015-duplicate-keys': require('babel-plugin-transform-es2015-duplicate-keys'),
  'transform-es2015-for-of': require('babel-plugin-transform-es2015-for-of'),
  'transform-es2015-function-name': require('babel-plugin-transform-es2015-function-name'),
  'transform-es2015-instanceof': require('babel-plugin-transform-es2015-instanceof'),
  'transform-es2015-literals': require('babel-plugin-transform-es2015-literals'),
  'transform-es2015-modules-amd': require('babel-plugin-transform-es2015-modules-amd'),
  'transform-es2015-modules-commonjs': require('babel-plugin-transform-es2015-modules-commonjs'),
  'transform-es2015-modules-systemjs': require('babel-plugin-transform-es2015-modules-systemjs'),
  'transform-es2015-modules-umd': require('babel-plugin-transform-es2015-modules-umd'),
  'transform-es2015-object-super': require('babel-plugin-transform-es2015-object-super'),
  'transform-es2015-parameters': require('babel-plugin-transform-es2015-parameters'),
  'transform-es2015-shorthand-properties': require('babel-plugin-transform-es2015-shorthand-properties'),
  'transform-es2015-spread': require('babel-plugin-transform-es2015-spread'),
  'transform-es2015-sticky-regex': require('babel-plugin-transform-es2015-sticky-regex'),
  'transform-es2015-template-literals': require('babel-plugin-transform-es2015-template-literals'),
  'transform-es2015-typeof-symbol': require('babel-plugin-transform-es2015-typeof-symbol'),
  'transform-es2015-unicode-regex': require('babel-plugin-transform-es2015-unicode-regex'),
  'transform-es3-member-expression-literals': require('babel-plugin-transform-es3-member-expression-literals'),
  'transform-es3-property-literals': require('babel-plugin-transform-es3-property-literals'),
  'transform-es5-property-mutators': require('babel-plugin-transform-es5-property-mutators'),
  'transform-eval': require('babel-plugin-transform-eval'),
  'transform-exponentiation-operator': require('babel-plugin-transform-exponentiation-operator'),
  'transform-export-extensions': require('babel-plugin-transform-export-extensions'),
  'transform-flow-comments': require('babel-plugin-transform-flow-comments'),
  'transform-flow-strip-types': require('babel-plugin-transform-flow-strip-types'),
  'transform-function-bind': require('babel-plugin-transform-function-bind'),
  'transform-jscript': require('babel-plugin-transform-jscript'),
  'transform-object-assign': require('babel-plugin-transform-object-assign'),
  'transform-object-rest-spread': require('babel-plugin-transform-object-rest-spread'),
  'transform-object-set-prototype-of-to-assign': require('babel-plugin-transform-object-set-prototype-of-to-assign'),
  'transform-proto-to-assign': require('babel-plugin-transform-proto-to-assign'),
  'transform-react-constant-elements': require('babel-plugin-transform-react-constant-elements'),
  'transform-react-display-name': require('babel-plugin-transform-react-display-name'),
  'transform-react-inline-elements': require('babel-plugin-transform-react-inline-elements'),
  'transform-react-jsx': require('babel-plugin-transform-react-jsx'),
  'transform-react-jsx-compat': require('babel-plugin-transform-react-jsx-compat'),
  'transform-react-jsx-self': require('babel-plugin-transform-react-jsx-self'),
  'transform-react-jsx-source': require('babel-plugin-transform-react-jsx-source'),
  'transform-regenerator': require('babel-plugin-transform-regenerator'),
  'transform-runtime': require('babel-plugin-transform-runtime'),
  'transform-strict-mode': require('babel-plugin-transform-strict-mode'),
  'undeclared-variables-check': require('babel-plugin-undeclared-variables-check'),
});

// All the presets we should bundle
registerPresets({
  es2015: require('babel-preset-es2015'),
  es2016: require('babel-preset-es2016'),
  es2017: require('babel-preset-es2017'),
  latest: require('babel-preset-latest'),
  react: require('babel-preset-react'),
  'stage-0': require('babel-preset-stage-0'),
  'stage-1': require('babel-preset-stage-1'),
  'stage-2': require('babel-preset-stage-2'),
  'stage-3': require('babel-preset-stage-3'),

  // ES2015 preset with es2015-modules-commonjs removed
  // Plugin list copied from babel-preset-es2015/index.js
  'es2015-no-commonjs': {
    plugins: [
      require("babel-plugin-transform-es2015-template-literals"),
      require("babel-plugin-transform-es2015-literals"),
      require("babel-plugin-transform-es2015-function-name"),
      require("babel-plugin-transform-es2015-arrow-functions"),
      require("babel-plugin-transform-es2015-block-scoped-functions"),
      require("babel-plugin-transform-es2015-classes"),
      require("babel-plugin-transform-es2015-object-super"),
      require("babel-plugin-transform-es2015-shorthand-properties"),
      require("babel-plugin-transform-es2015-computed-properties"),
      require("babel-plugin-transform-es2015-for-of"),
      require("babel-plugin-transform-es2015-sticky-regex"),
      require("babel-plugin-transform-es2015-unicode-regex"),
      require("babel-plugin-check-es2015-constants"),
      require("babel-plugin-transform-es2015-spread"),
      require("babel-plugin-transform-es2015-parameters"),
      require("babel-plugin-transform-es2015-destructuring"),
      require("babel-plugin-transform-es2015-block-scoping"),
      require("babel-plugin-transform-es2015-typeof-symbol"),
      [require("babel-plugin-transform-regenerator"), { async: false, asyncGenerators: false }],
    ]
  },

  // ES2015 preset with plugins set to loose mode.
  // Based off https://github.com/bkonkle/babel-preset-es2015-loose/blob/master/index.js
  'es2015-loose': {
    plugins: [
      [require("babel-plugin-transform-es2015-template-literals"), { loose: true }],
      require("babel-plugin-transform-es2015-literals"),
      require("babel-plugin-transform-es2015-function-name"),
      require("babel-plugin-transform-es2015-arrow-functions"),
      require("babel-plugin-transform-es2015-block-scoped-functions"),
      [require("babel-plugin-transform-es2015-classes"), { loose: true }],
      require("babel-plugin-transform-es2015-object-super"),
      require("babel-plugin-transform-es2015-shorthand-properties"),
      require("babel-plugin-transform-es2015-duplicate-keys"),
      [require("babel-plugin-transform-es2015-computed-properties"), { loose: true }],
      [require("babel-plugin-transform-es2015-for-of"), { loose: true }],
      require("babel-plugin-transform-es2015-sticky-regex"),
      require("babel-plugin-transform-es2015-unicode-regex"),
      require("babel-plugin-check-es2015-constants"),
      [require("babel-plugin-transform-es2015-spread"), { loose: true }],
      require("babel-plugin-transform-es2015-parameters"),
      [require("babel-plugin-transform-es2015-destructuring"), { loose: true }],
      require("babel-plugin-transform-es2015-block-scoping"),
      require("babel-plugin-transform-es2015-typeof-symbol"),
      [require("babel-plugin-transform-es2015-modules-commonjs"), { loose: true }],
      [require("babel-plugin-transform-regenerator"), { async: false, asyncGenerators: false }],
    ]
  },
});

export const version = VERSION;

// Listen for load event if we're in a browser and then kick off finding and
// running of scripts with "text/babel" type.
if (typeof window !== 'undefined' && window && window.addEventListener) {
  window.addEventListener('DOMContentLoaded', transformScriptTags, false);
}

/**
 * Transform <script> tags with "text/babel" type.
 * @param {Array} scriptTags specify script tags to transform, transform all in the <head> if not given
 */
export function transformScriptTags(scriptTags) {
  runScripts(transform, scriptTags);
}

/**
 * Disables automatic transformation of <script> tags with "text/babel" type.
 */
export function disableScriptTags() {
  window.removeEventListener('DOMContentLoaded', transformScriptTags);
}

<commit_msg>Register `inline-replace-variables` plugin<commit_after>import * as Babel from 'babel-core';

import {runScripts} from './transformScriptTags';

const isArray = Array.isArray || (arg => Object.prototype.toString.call(arg) === '[object Array]');

/**
 * Loads the given name (or [name, options] pair) from the given table object
 * holding the available presets or plugins.
 *
 * Returns undefined if the preset or plugin is not available; passes through
 * name unmodified if it (or the first element of the pair) is not a string.
 */
function loadBuiltin(builtinTable, name) {
  if (isArray(name) && typeof name[0] === 'string') {
    if (builtinTable.hasOwnProperty(name[0])) {
      return [builtinTable[name[0]]].concat(name.slice(1));
    }
    return;
  } else if (typeof name === 'string') {
    return builtinTable[name];
  }
  // Could be an actual preset/plugin module
  return name;
}

/**
 * Parses plugin names and presets from the specified options.
 */
function processOptions(options) {
  // Parse preset names
  const presets = (options.presets || []).map(presetName => {
    const preset = loadBuiltin(availablePresets, presetName);

    if (preset) {
      // workaround for babel issue
      // at some point, babel copies the preset, losing the non-enumerable
      // buildPreset key; convert it into an enumerable key.
      if (isArray(preset) && typeof preset[0] === 'object' && preset[0].hasOwnProperty('buildPreset')) {
        preset[0] = { ...preset[0], buildPreset: preset[0].buildPreset }
      }
    } else {
      throw new Error(`Invalid preset specified in Babel options: "${presetName}"`);
    }
    return preset;
  });

  // Parse plugin names
  const plugins = (options.plugins || []).map(pluginName => {
    const plugin = loadBuiltin(availablePlugins, pluginName);

    if (!plugin) {
      throw new Error(`Invalid plugin specified in Babel options: "${pluginName}"`);
    }
    return plugin;
  });

  return {
    babelrc: false,
    ...options,
    presets,
    plugins,
  }
}

export function transform(code, options) {
  return Babel.transform(code, processOptions(options));
}

export function transformFromAst(ast, code, options) {
  return Babel.transformFromAst(ast, code, processOptions(options));
}
export const availablePlugins = {};
export const availablePresets = {};

/**
 * Registers a named plugin for use with Babel.
 */
export function registerPlugin(name, plugin) {
  if (availablePlugins.hasOwnProperty(name)) {
    console.warn(`A plugin named "${name}" is already registered, it will be overridden`);
  }
  availablePlugins[name] = plugin;
}
/**
 * Registers multiple plugins for use with Babel. `newPlugins` should be an object where the key
 * is the name of the plugin, and the value is the plugin itself.
 */
export function registerPlugins(newPlugins) {
  Object.keys(newPlugins).forEach(name => registerPlugin(name, newPlugins[name]));
}

/**
 * Registers a named preset for use with Babel.
 */
export function registerPreset(name, preset) {
  if (availablePresets.hasOwnProperty(name)) {
    console.warn(`A preset named "${name}" is already registered, it will be overridden`);
  }
  availablePresets[name] = preset;
}
/**
 * Registers multiple presets for use with Babel. `newPresets` should be an object where the key
 * is the name of the preset, and the value is the preset itself.
 */
export function registerPresets(newPresets) {
  Object.keys(newPresets).forEach(name => registerPreset(name, newPresets[name]));
}

// All the plugins we should bundle
registerPlugins({
  'check-es2015-constants': require('babel-plugin-check-es2015-constants'),
  'external-helpers': require('babel-plugin-external-helpers'),
  'inline-replace-variables': require('babel-plugin-inline-replace-variables'),
  'syntax-async-functions': require('babel-plugin-syntax-async-functions'),
  'syntax-async-generators': require('babel-plugin-syntax-async-generators'),
  'syntax-class-constructor-call': require('babel-plugin-syntax-class-constructor-call'),
  'syntax-class-properties': require('babel-plugin-syntax-class-properties'),
  'syntax-decorators': require('babel-plugin-syntax-decorators'),
  'syntax-do-expressions': require('babel-plugin-syntax-do-expressions'),
  'syntax-exponentiation-operator': require('babel-plugin-syntax-exponentiation-operator'),
  'syntax-export-extensions': require('babel-plugin-syntax-export-extensions'),
  'syntax-flow': require('babel-plugin-syntax-flow'),
  'syntax-function-bind': require('babel-plugin-syntax-function-bind'),
  'syntax-function-sent': require('babel-plugin-syntax-function-sent'),
  'syntax-jsx': require('babel-plugin-syntax-jsx'),
  'syntax-object-rest-spread': require('babel-plugin-syntax-object-rest-spread'),
  'syntax-trailing-function-commas': require('babel-plugin-syntax-trailing-function-commas'),
  'transform-async-functions': require('babel-plugin-transform-async-functions'),
  'transform-async-to-generator': require('babel-plugin-transform-async-to-generator'),
  'transform-async-to-module-method': require('babel-plugin-transform-async-to-module-method'),
  'transform-class-constructor-call': require('babel-plugin-transform-class-constructor-call'),
  'transform-class-properties': require('babel-plugin-transform-class-properties'),
  'transform-decorators': require('babel-plugin-transform-decorators'),
  'transform-decorators-legacy': require('babel-plugin-transform-decorators-legacy').default, // <- No clue. Nope.
  'transform-do-expressions': require('babel-plugin-transform-do-expressions'),
  'transform-es2015-arrow-functions': require('babel-plugin-transform-es2015-arrow-functions'),
  'transform-es2015-block-scoped-functions': require('babel-plugin-transform-es2015-block-scoped-functions'),
  'transform-es2015-block-scoping': require('babel-plugin-transform-es2015-block-scoping'),
  'transform-es2015-classes': require('babel-plugin-transform-es2015-classes'),
  'transform-es2015-computed-properties': require('babel-plugin-transform-es2015-computed-properties'),
  'transform-es2015-destructuring': require('babel-plugin-transform-es2015-destructuring'),
  'transform-es2015-duplicate-keys': require('babel-plugin-transform-es2015-duplicate-keys'),
  'transform-es2015-for-of': require('babel-plugin-transform-es2015-for-of'),
  'transform-es2015-function-name': require('babel-plugin-transform-es2015-function-name'),
  'transform-es2015-instanceof': require('babel-plugin-transform-es2015-instanceof'),
  'transform-es2015-literals': require('babel-plugin-transform-es2015-literals'),
  'transform-es2015-modules-amd': require('babel-plugin-transform-es2015-modules-amd'),
  'transform-es2015-modules-commonjs': require('babel-plugin-transform-es2015-modules-commonjs'),
  'transform-es2015-modules-systemjs': require('babel-plugin-transform-es2015-modules-systemjs'),
  'transform-es2015-modules-umd': require('babel-plugin-transform-es2015-modules-umd'),
  'transform-es2015-object-super': require('babel-plugin-transform-es2015-object-super'),
  'transform-es2015-parameters': require('babel-plugin-transform-es2015-parameters'),
  'transform-es2015-shorthand-properties': require('babel-plugin-transform-es2015-shorthand-properties'),
  'transform-es2015-spread': require('babel-plugin-transform-es2015-spread'),
  'transform-es2015-sticky-regex': require('babel-plugin-transform-es2015-sticky-regex'),
  'transform-es2015-template-literals': require('babel-plugin-transform-es2015-template-literals'),
  'transform-es2015-typeof-symbol': require('babel-plugin-transform-es2015-typeof-symbol'),
  'transform-es2015-unicode-regex': require('babel-plugin-transform-es2015-unicode-regex'),
  'transform-es3-member-expression-literals': require('babel-plugin-transform-es3-member-expression-literals'),
  'transform-es3-property-literals': require('babel-plugin-transform-es3-property-literals'),
  'transform-es5-property-mutators': require('babel-plugin-transform-es5-property-mutators'),
  'transform-eval': require('babel-plugin-transform-eval'),
  'transform-exponentiation-operator': require('babel-plugin-transform-exponentiation-operator'),
  'transform-export-extensions': require('babel-plugin-transform-export-extensions'),
  'transform-flow-comments': require('babel-plugin-transform-flow-comments'),
  'transform-flow-strip-types': require('babel-plugin-transform-flow-strip-types'),
  'transform-function-bind': require('babel-plugin-transform-function-bind'),
  'transform-jscript': require('babel-plugin-transform-jscript'),
  'transform-object-assign': require('babel-plugin-transform-object-assign'),
  'transform-object-rest-spread': require('babel-plugin-transform-object-rest-spread'),
  'transform-object-set-prototype-of-to-assign': require('babel-plugin-transform-object-set-prototype-of-to-assign'),
  'transform-proto-to-assign': require('babel-plugin-transform-proto-to-assign'),
  'transform-react-constant-elements': require('babel-plugin-transform-react-constant-elements'),
  'transform-react-display-name': require('babel-plugin-transform-react-display-name'),
  'transform-react-inline-elements': require('babel-plugin-transform-react-inline-elements'),
  'transform-react-jsx': require('babel-plugin-transform-react-jsx'),
  'transform-react-jsx-compat': require('babel-plugin-transform-react-jsx-compat'),
  'transform-react-jsx-self': require('babel-plugin-transform-react-jsx-self'),
  'transform-react-jsx-source': require('babel-plugin-transform-react-jsx-source'),
  'transform-regenerator': require('babel-plugin-transform-regenerator'),
  'transform-runtime': require('babel-plugin-transform-runtime'),
  'transform-strict-mode': require('babel-plugin-transform-strict-mode'),
  'undeclared-variables-check': require('babel-plugin-undeclared-variables-check'),
});

// All the presets we should bundle
registerPresets({
  es2015: require('babel-preset-es2015'),
  es2016: require('babel-preset-es2016'),
  es2017: require('babel-preset-es2017'),
  latest: require('babel-preset-latest'),
  react: require('babel-preset-react'),
  'stage-0': require('babel-preset-stage-0'),
  'stage-1': require('babel-preset-stage-1'),
  'stage-2': require('babel-preset-stage-2'),
  'stage-3': require('babel-preset-stage-3'),

  // ES2015 preset with es2015-modules-commonjs removed
  // Plugin list copied from babel-preset-es2015/index.js
  'es2015-no-commonjs': {
    plugins: [
      require("babel-plugin-transform-es2015-template-literals"),
      require("babel-plugin-transform-es2015-literals"),
      require("babel-plugin-transform-es2015-function-name"),
      require("babel-plugin-transform-es2015-arrow-functions"),
      require("babel-plugin-transform-es2015-block-scoped-functions"),
      require("babel-plugin-transform-es2015-classes"),
      require("babel-plugin-transform-es2015-object-super"),
      require("babel-plugin-transform-es2015-shorthand-properties"),
      require("babel-plugin-transform-es2015-computed-properties"),
      require("babel-plugin-transform-es2015-for-of"),
      require("babel-plugin-transform-es2015-sticky-regex"),
      require("babel-plugin-transform-es2015-unicode-regex"),
      require("babel-plugin-check-es2015-constants"),
      require("babel-plugin-transform-es2015-spread"),
      require("babel-plugin-transform-es2015-parameters"),
      require("babel-plugin-transform-es2015-destructuring"),
      require("babel-plugin-transform-es2015-block-scoping"),
      require("babel-plugin-transform-es2015-typeof-symbol"),
      [require("babel-plugin-transform-regenerator"), { async: false, asyncGenerators: false }],
    ]
  },

  // ES2015 preset with plugins set to loose mode.
  // Based off https://github.com/bkonkle/babel-preset-es2015-loose/blob/master/index.js
  'es2015-loose': {
    plugins: [
      [require("babel-plugin-transform-es2015-template-literals"), { loose: true }],
      require("babel-plugin-transform-es2015-literals"),
      require("babel-plugin-transform-es2015-function-name"),
      require("babel-plugin-transform-es2015-arrow-functions"),
      require("babel-plugin-transform-es2015-block-scoped-functions"),
      [require("babel-plugin-transform-es2015-classes"), { loose: true }],
      require("babel-plugin-transform-es2015-object-super"),
      require("babel-plugin-transform-es2015-shorthand-properties"),
      require("babel-plugin-transform-es2015-duplicate-keys"),
      [require("babel-plugin-transform-es2015-computed-properties"), { loose: true }],
      [require("babel-plugin-transform-es2015-for-of"), { loose: true }],
      require("babel-plugin-transform-es2015-sticky-regex"),
      require("babel-plugin-transform-es2015-unicode-regex"),
      require("babel-plugin-check-es2015-constants"),
      [require("babel-plugin-transform-es2015-spread"), { loose: true }],
      require("babel-plugin-transform-es2015-parameters"),
      [require("babel-plugin-transform-es2015-destructuring"), { loose: true }],
      require("babel-plugin-transform-es2015-block-scoping"),
      require("babel-plugin-transform-es2015-typeof-symbol"),
      [require("babel-plugin-transform-es2015-modules-commonjs"), { loose: true }],
      [require("babel-plugin-transform-regenerator"), { async: false, asyncGenerators: false }],
    ]
  },
});

export const version = VERSION;

// Listen for load event if we're in a browser and then kick off finding and
// running of scripts with "text/babel" type.
if (typeof window !== 'undefined' && window && window.addEventListener) {
  window.addEventListener('DOMContentLoaded', transformScriptTags, false);
}

/**
 * Transform <script> tags with "text/babel" type.
 * @param {Array} scriptTags specify script tags to transform, transform all in the <head> if not given
 */
export function transformScriptTags(scriptTags) {
  runScripts(transform, scriptTags);
}

/**
 * Disables automatic transformation of <script> tags with "text/babel" type.
 */
export function disableScriptTags() {
  window.removeEventListener('DOMContentLoaded', transformScriptTags);
}

<|endoftext|>


<commit_before>'use strict';

const app = require('./app');
const port = app.get('port');
const server = app.listen(port);

server.on('listening', () =>
	console.log(`Feathers application started on ${app.get('host')}:${port} and public folder of ${app.get('public')}` )
);

<commit_msg>log public folder in index.js<commit_after>'use strict';
const path = require('path');
const app = require('./app');
const port = app.get('port');
const server = app.listen(port);

console.log(path.parse(__dirname));
server.on('listening', () =>
	console.log(`Feathers application started on ${app.get('host')}:${port} and public folder of ${app.get('public')}` )
);

<|endoftext|>


<commit_before>'use strict'

const download = require('./download')
const install = require('./install')
const environment = require('./environment')

// Here lie the bodies of promises, killed in
// the name of better garbage collection
download(function () {
  install(function (variables) {
    environment(variables)
  })
})
<commit_msg>:memo: For shame, whitespace<commit_after>'use strict'

const download = require('./download')
const install = require('./install')
const environment = require('./environment')

// Here lie the bodies of promises, killed in
// the name of better garbage collection
download(function () {
  install(function (variables) {
    environment(variables)
  })
})
<|endoftext|>


<commit_before>import { OAuth2Strategy, InternalOAuthError } from 'passport-oauth';

/**
 * `Strategy` constructor.
 * The GitHub authentication strategy authenticates requests by delegating to GitHub using OAuth2 access tokens.
 * Applications must supply a `verify` callback which accepts a accessToken, refreshToken, profile and callback.
 * Callback supplying a `user`, which should be set to `false` if the credentials are not valid.
 * If an exception occurs, `error` should be set.
 *
 * Options:
 * - clientID          Identifies client to GitHub App
 * - clientSecret      Secret used to establish ownership of the consumer key
 * - scope             Scope to get user's private emails
 * - passReqToCallback If need, pass req to verify callback
 *
 * @param {Object} _options
 * @param {Function} _verify
 * @example
 * passport.use(new GitHubTokenStrategy({
 *   clientID: '123456789',
 *   clientSecret: 'shhh-its-a-secret',
 *   scope: 'user:email',
 * }), function(accessToken, refreshToken, profile, next) {
 *   User.findOrCreate({githubId: profile.id}, function(error, user) {
 *     next(error, user);
 *   })
 * })
 */
export default class GitHubTokenStrategy extends OAuth2Strategy {
  constructor(_options, _verify) {
    let options = _options || {};
    let verify = _verify;

    options.authorizationURL = options.authorizationURL || 'https://github.com/login/oauth/authorize';
    options.tokenURL = options.tokenURL || 'https://github.com/login/oauth/access_token';

    super(options, verify);

    this.name = 'github-token';
    this._accessTokenField = options.accessTokenField || 'access_token';
    this._refreshTokenField = options.refreshTokenField || 'refresh_token';
    this._profileURL = options.profileURL || 'https://api.github.com/user';
    this._passReqToCallback = options.passReqToCallback;

    this._oauth2.useAuthorizationHeaderforGET(true);
  }

  /**
   * Authenticate method
   * @param {Object} req
   * @param {Object} options
   * @returns {*}
   */
  authenticate(req, options) {
    let accessToken = (req.body && req.body[this._accessTokenField]) || (req.query && req.query[this._accessTokenField]);
    let refreshToken = (req.body && req.body[this._refreshTokenField]) || (req.query && req.query[this._refreshTokenField]);

    if (!accessToken) return this.fail({ message: `You should provide ${this._accessTokenField}` });

    this._loadUserProfile(accessToken, (error, profile) => {
      if (error) return this.error(error);

      const verified = (error, user, info) => {
        if (error) return this.error(error);
        if (!user) return this.fail(info);

        return this.success(user, info);
      };

      if (this._passReqToCallback) {
        this._verify(req, accessToken, refreshToken, profile, verified);
      } else {
        this._verify(accessToken, refreshToken, profile, verified);
      }
    });
  }

  /**
   * Parse user profile
   * @param {String} accessToken GitHub OAuth2 access token
   * @param {Function} done
   */
  userProfile(accessToken, done) {
    this._oauth2.get(this._profileURL, accessToken, (error, body, res) => {
      if (error) {
        try {
          let errorJSON = JSON.parse(error.data);
          return done(new InternalOAuthError(errorJSON.message, error.statusCode));
        } catch (_) {
          return done(new InternalOAuthError('Failed to fetch user profile', error));
        }
      }

      let profile = {};

      try {
        let json = JSON.parse(body);
        profile = {
          provider: 'github',
          id: json.id,
          username: json.login,
          displayName: json.name || '',
          name: {
            familyName: json.name ? json.name.split(' ', 2)[1] || '' : '',
            givenName: json.name ? json.name.split(' ', 2)[0] || '' : ''
          },
          emails: json.email && [{ value: json.email }],
          photos: [],
          _raw: body,
          _json: json
        };
      } catch (e) {
        return done(e);
      }

      if (this._scope && this._scope.indexOf('user:email') !== -1) {
        this._oauth2._request('GET', this._profileURL + '/emails', { 'Accept': 'application/vnd.github.v3+json' }, '', accessToken, function (error, body, res) {
          if (error) return done(null, profile);

          var json;
          try {
            json = JSON.parse(body);
          } catch (_) {
            return done(null, profile);
          }

          if (!json.length) return done(null, profile);

          profile.emails = profile.emails || [];
          var publicEmail = profile.emails[0];

          (json).forEach(function (email) {
            if (publicEmail && publicEmail.value == email.email) {
              profile.emails[0].primary = email.primary;
              profile.emails[0].verified = email.verified;
            } else {
              profile.emails.push({ value: email.email, primary: email.primary, verified: email.verified })
            }
          });

          done(null, profile);
        });
      }
      else {
        done(null, profile);
      }
    });
  }
}
<commit_msg>Sending access_token on request header (#179)<commit_after>import { OAuth2Strategy, InternalOAuthError } from 'passport-oauth';

/**
 * `Strategy` constructor.
 * The GitHub authentication strategy authenticates requests by delegating to GitHub using OAuth2 access tokens.
 * Applications must supply a `verify` callback which accepts a accessToken, refreshToken, profile and callback.
 * Callback supplying a `user`, which should be set to `false` if the credentials are not valid.
 * If an exception occurs, `error` should be set.
 *
 * Options:
 * - clientID          Identifies client to GitHub App
 * - clientSecret      Secret used to establish ownership of the consumer key
 * - scope             Scope to get user's private emails
 * - passReqToCallback If need, pass req to verify callback
 *
 * @param {Object} _options
 * @param {Function} _verify
 * @example
 * passport.use(new GitHubTokenStrategy({
 *   clientID: '123456789',
 *   clientSecret: 'shhh-its-a-secret',
 *   scope: 'user:email',
 * }), function(accessToken, refreshToken, profile, next) {
 *   User.findOrCreate({githubId: profile.id}, function(error, user) {
 *     next(error, user);
 *   })
 * })
 */
export default class GitHubTokenStrategy extends OAuth2Strategy {
  constructor(_options, _verify) {
    let options = _options || {};
    let verify = _verify;

    options.authorizationURL = options.authorizationURL || 'https://github.com/login/oauth/authorize';
    options.tokenURL = options.tokenURL || 'https://github.com/login/oauth/access_token';

    super(options, verify);

    this.name = 'github-token';
    this._accessTokenField = options.accessTokenField || 'access_token';
    this._refreshTokenField = options.refreshTokenField || 'refresh_token';
    this._profileURL = options.profileURL || 'https://api.github.com/user';
    this._passReqToCallback = options.passReqToCallback;

    this._oauth2.useAuthorizationHeaderforGET(true);
  }

  /**
   * Authenticate method
   * @param {Object} req
   * @param {Object} options
   * @returns {*}
   */
  authenticate(req, options) {
    let accessToken = (req.body && req.body[this._accessTokenField]) || (req.query && req.query[this._accessTokenField]);
    let refreshToken = (req.body && req.body[this._refreshTokenField]) || (req.query && req.query[this._refreshTokenField]);

    if (!accessToken) return this.fail({ message: `You should provide ${this._accessTokenField}` });

    this._loadUserProfile(accessToken, (error, profile) => {
      if (error) return this.error(error);

      const verified = (error, user, info) => {
        if (error) return this.error(error);
        if (!user) return this.fail(info);

        return this.success(user, info);
      };

      if (this._passReqToCallback) {
        this._verify(req, accessToken, refreshToken, profile, verified);
      } else {
        this._verify(accessToken, refreshToken, profile, verified);
      }
    });
  }

  /**
   * Parse user profile
   * @param {String} accessToken GitHub OAuth2 access token
   * @param {Function} done
   */
  userProfile(accessToken, done) {
    this._oauth2.get(this._profileURL, accessToken, (error, body, res) => {
      if (error) {
        try {
          let errorJSON = JSON.parse(error.data);
          return done(new InternalOAuthError(errorJSON.message, error.statusCode));
        } catch (_) {
          return done(new InternalOAuthError('Failed to fetch user profile', error));
        }
      }

      let profile = {};

      try {
        let json = JSON.parse(body);
        profile = {
          provider: 'github',
          id: json.id,
          username: json.login,
          displayName: json.name || '',
          name: {
            familyName: json.name ? json.name.split(' ', 2)[1] || '' : '',
            givenName: json.name ? json.name.split(' ', 2)[0] || '' : ''
          },
          emails: json.email && [{ value: json.email }],
          photos: [],
          _raw: body,
          _json: json
        };
      } catch (e) {
        return done(e);
      }

      if (this._scope && this._scope.indexOf('user:email') !== -1) {
        this._oauth2.get(this._profileURL + '/emails', accessToken, function (error, body, res) {
          if (error) return done(null, profile);

          var json;
          try {
            json = JSON.parse(body);
          } catch (_) {
            return done(null, profile);
          }

          if (!json.length) return done(null, profile);

          profile.emails = profile.emails || [];
          var publicEmail = profile.emails[0];

          (json).forEach(function (email) {
            if (publicEmail && publicEmail.value == email.email) {
              profile.emails[0].primary = email.primary;
              profile.emails[0].verified = email.verified;
            } else {
              profile.emails.push({ value: email.email, primary: email.primary, verified: email.verified })
            }
          });

          done(null, profile);
        });
      }
      else {
        done(null, profile);
      }
    });
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import { render } from 'react-dom';
import { Router, useRouterHistory } from 'react-router';
import { syncHistoryWithStore, routerReducer } from 'react-router-redux';
import { Provider } from 'react-redux';
import createHistory from 'history/lib/createBrowserHistory';
import 'font-awesome/css/font-awesome.css';
import Main from './main';
import Store from './store';
import ListRoute from './pages/list/route';
import PostageRoute from './pages/postage/route';

let history = useRouterHistory(createHistory)({
  basename: process.env.SITE_BASE || document.head.baseURI,
});

Store.addReducers({
  routing: routerReducer,
});

// Create an enhanced history that syncs navigation events with the store
history = syncHistoryWithStore(history, Store.getStore());
const rootRoute = {
  path: '/',
  component: Main,
  indexRoute: {
    onEnter: (nextState, replace) => replace('/list/1'),
  },
  childRoutes: [
    ListRoute,
    PostageRoute,
  ],
};

// Declarative route configuration (could also load this config lazily
// instead, all you really need is a single root route, you don't need to
// colocate the entire config).
render((<Provider store={Store.getStore()}>
  <Router history={history} routes={rootRoute} />
</Provider>), document.getElementById('main'));
<commit_msg>更新 history basename 的设置<commit_after>import React from 'react';
import { render } from 'react-dom';
import { Router, useRouterHistory } from 'react-router';
import { syncHistoryWithStore, routerReducer } from 'react-router-redux';
import { Provider } from 'react-redux';
import createHistory from 'history/lib/createBrowserHistory';
import 'font-awesome/css/font-awesome.css';
import Main from './main';
import Store from './store';
import ListRoute from './pages/list/route';
import PostageRoute from './pages/postage/route';

let history = useRouterHistory(createHistory)({
  basename: `${document.location.protocol}://${document.location.host}`,
});

Store.addReducers({
  routing: routerReducer,
});

// Create an enhanced history that syncs navigation events with the store
history = syncHistoryWithStore(history, Store.getStore());
const rootRoute = {
  path: '/',
  component: Main,
  indexRoute: {
    onEnter: (nextState, replace) => replace('/list/1'),
  },
  childRoutes: [
    ListRoute,
    PostageRoute,
  ],
};

// Declarative route configuration (could also load this config lazily
// instead, all you really need is a single root route, you don't need to
// colocate the entire config).
render((<Provider store={Store.getStore()}>
  <Router history={history} routes={rootRoute} />
</Provider>), document.getElementById('main'));
<|endoftext|>


<commit_before>import { initializeOptions } from './url'
import { initializeSliders, resizeSliders } from './sliders'
import { initializeShapes } from './shapes'
import { initializeColors } from './colors'

function ready() {
  const options = initializeOptions()
  initializeSliders(options)
  initializeShapes(options)
  initializeColors(options)

  window.addEventListener('resize', resizeSliders)
}

if (document.readyState !== 'loading') {
  ready()
} else {
  document.addEventListener('DOMContentLoaded', ready)
}
<commit_msg>Made ready run after CSS is loaded.<commit_after>import { initializeOptions } from './url'
import { initializeSliders, resizeSliders } from './sliders'
import { initializeShapes } from './shapes'
import { initializeColors } from './colors'

function ready() {
  const options = initializeOptions()
  initializeSliders(options)
  initializeShapes(options)
  initializeColors(options)

  window.addEventListener('resize', resizeSliders)
}

if (document.readyState === 'complete') {
  ready()
} else {
  window.addEventListener('load', ready)
}
<|endoftext|>


<commit_before>'use strict';

const inquirer = require('inquirer');
const getProjectOptions = require('./get-project-options');
const getPackageName = require('./get-package-name');
const getPackageVersion = require('./get-package-version');
const getVersions = require('boilerplate-update/src/get-versions');
const getProjectVersion = require('./get-project-version');
const _getTagVersion = require('./get-tag-version');
const getRemoteUrl = require('./get-remote-url');
const boilerplateUpdate = require('boilerplate-update');
const getStartAndEndCommands = require('./get-start-and-end-commands');
const parseBlueprint = require('./parse-blueprint');
const downloadPackage = require('./download-package');
const loadBlueprintFile = require('./load-blueprint-file');
const loadSafeBlueprintFile = require('./load-safe-blueprint-file');
const saveBlueprint = require('./save-blueprint');
const saveDefaultBlueprint = require('./save-default-blueprint');
const checkForBlueprintUpdates = require('./check-for-blueprint-updates');
const loadSafeDefaultBlueprint = require('./load-safe-default-blueprint');
const loadSafeBlueprint = require('./load-safe-blueprint');
const stageBlueprintFile = require('./stage-blueprint-file');
const getBlueprintFilePath = require('./get-blueprint-file-path');
const isDefaultBlueprint = require('./is-default-blueprint');
const findBlueprint = require('./find-blueprint');

const {
  'to': { default: toDefault },
  'codemods-url': { default: codemodsUrlDefault }
} = require('./args');

function formatBlueprintLine({
  name,
  currentVersion,
  latestVersion
}) {
  return `${name}, current: ${currentVersion}, latest: ${latestVersion}`;
}

module.exports = async function emberCliUpdate({
  blueprint: _blueprint,
  from,
  to,
  resolveConflicts,
  runCodemods,
  codemodsUrl = codemodsUrlDefault,
  codemodsJson,
  reset,
  compareOnly,
  statsOnly,
  listCodemods,
  createCustomDiff,
  wasRunAsExecutable
}) {
  let cwd = process.cwd();

  let emberCliUpdateJson = await loadSafeBlueprintFile(cwd);

  let blueprint;
  let url;
  let isPersistedBlueprint;

  if (_blueprint) {
    let parsedBlueprint = await parseBlueprint(_blueprint);
    url = parsedBlueprint.url;

    let { name } = parsedBlueprint;
    if (!name) {
      let downloadedPackage = await downloadPackage(null, url, toDefault);
      name = downloadedPackage.name;
    }

    let packageName = name;

    let existingBlueprint = findBlueprint(emberCliUpdateJson, packageName, name);
    if (existingBlueprint) {
      isPersistedBlueprint = true;
      blueprint = loadSafeBlueprint(existingBlueprint);
    } else {
      blueprint = loadSafeBlueprint({
        packageName,
        name,
        location: parsedBlueprint.location
      });
    }

    if (from) {
      blueprint.version = from;
    }

    if (!blueprint.version && !reset) {
      throw new Error('A custom blueprint cannot detect --from. You must supply it.');
    }
  } else {
    let { blueprints } = emberCliUpdateJson;

    if (!blueprints.length) {
      blueprint = loadSafeDefaultBlueprint();
    } else {
      isPersistedBlueprint = true;

      let blueprintUpdates = await checkForBlueprintUpdates(blueprints);

      let areAllUpToDate = blueprintUpdates.every(blueprintUpdate => blueprintUpdate.isUpToDate);
      if (areAllUpToDate) {
        return `${blueprintUpdates.map(formatBlueprintLine).join(`
`)}

All blueprints are up-to-date!`;
      }

      let choicesByName = blueprintUpdates.reduce((choices, blueprintUpdate) => {
        let name = formatBlueprintLine(blueprintUpdate);
        choices[name] = {
          blueprintUpdate,
          choice: {
            name,
            disabled: blueprintUpdate.isUpToDate
          }
        };
        return choices;
      }, {});

      let answer = await inquirer.prompt([{
        type: 'list',
        message: 'Blueprint updates have been found. Which one would you like to update?',
        name: 'blueprint',
        choices: Object.values(choicesByName).map(({ choice }) => choice)
      }]);

      let { blueprintUpdate } = choicesByName[answer.blueprint];

      let existingBlueprint = findBlueprint(emberCliUpdateJson, blueprintUpdate.packageName, blueprintUpdate.name);
      blueprint = loadSafeBlueprint(existingBlueprint);
    }
  }

  if (blueprint.location && !url) {
    url = (await parseBlueprint(blueprint.location)).url;
  }

  let isCustomBlueprint = !isDefaultBlueprint(blueprint);

  if (isCustomBlueprint) {
    createCustomDiff = true;
  }

  let endBlueprint;

  let result = await (await boilerplateUpdate({
    projectOptions: ({ packageJson }) => getProjectOptions(packageJson, blueprint),
    mergeOptions: async function mergeOptions({
      packageJson,
      projectOptions
    }) {
      if (createCustomDiff && projectOptions.includes('glimmer')) {
        // ember-cli doesn't have a way to use non-latest blueprint versions
        // TODO: The above is not true anymore. This can be fixed.
        throw 'cannot checkout older versions of glimmer blueprint';
      }

      let startVersion;
      let endVersion;
      let startBlueprint;

      if (!isCustomBlueprint && createCustomDiff) {
        blueprint = loadSafeDefaultBlueprint(projectOptions, blueprint.version);
      }

      if (isCustomBlueprint) {
        startBlueprint = { ...blueprint, ...await downloadPackage(blueprint.name, url, blueprint.version) };
        endBlueprint = { ...blueprint, ...await downloadPackage(blueprint.name, url, to) };

        startVersion = startBlueprint.version;
        endVersion = endBlueprint.version;
      } else {
        let packageName = getPackageName(projectOptions);
        let packageVersion = getPackageVersion(packageJson, packageName);

        let versions = await getVersions(packageName);

        let getTagVersion = _getTagVersion(versions, packageName);

        if (from) {
          startVersion = await getTagVersion(from);
        } else {
          startVersion = getProjectVersion(packageVersion, versions, projectOptions);
        }

        endVersion = await getTagVersion(to);

        startBlueprint = { ...blueprint, version: startVersion };
        endBlueprint = { ...blueprint, version: endVersion };
      }

      let customDiffOptions;
      if (createCustomDiff) {
        customDiffOptions = getStartAndEndCommands({
          packageJson,
          startBlueprint,
          endBlueprint
        });
      }

      return {
        startVersion,
        endVersion,
        customDiffOptions
      };
    },
    remoteUrl: ({ projectOptions }) => getRemoteUrl(projectOptions),
    compareOnly,
    resolveConflicts,
    reset,
    statsOnly,
    listCodemods,
    runCodemods,
    codemodsUrl,
    codemodsJson,
    createCustomDiff,
    ignoredFiles: [await getBlueprintFilePath(cwd)],
    wasRunAsExecutable
  })).promise;

  if (_blueprint) {
    let emberCliUpdateJson = await loadBlueprintFile(cwd);

    // If you don't have a state file, save the default blueprint,
    // even if you are currently working on a custom blueprint.
    if (!emberCliUpdateJson || !isCustomBlueprint) {
      await saveDefaultBlueprint({
        cwd
      });
    }

    if (isCustomBlueprint) {
      await saveBlueprint({
        cwd,
        blueprint: endBlueprint
      });
    }

    if (!reset) {
      await stageBlueprintFile(cwd);
    }
  } else if (isPersistedBlueprint) {
    await saveBlueprint({
      cwd,
      blueprint: endBlueprint
    });

    if (!reset) {
      await stageBlueprintFile(cwd);
    }
  }

  return result;
};
<commit_msg>rename packageUrl<commit_after>'use strict';

const inquirer = require('inquirer');
const getProjectOptions = require('./get-project-options');
const getPackageName = require('./get-package-name');
const getPackageVersion = require('./get-package-version');
const getVersions = require('boilerplate-update/src/get-versions');
const getProjectVersion = require('./get-project-version');
const _getTagVersion = require('./get-tag-version');
const getRemoteUrl = require('./get-remote-url');
const boilerplateUpdate = require('boilerplate-update');
const getStartAndEndCommands = require('./get-start-and-end-commands');
const parseBlueprint = require('./parse-blueprint');
const downloadPackage = require('./download-package');
const loadBlueprintFile = require('./load-blueprint-file');
const loadSafeBlueprintFile = require('./load-safe-blueprint-file');
const saveBlueprint = require('./save-blueprint');
const saveDefaultBlueprint = require('./save-default-blueprint');
const checkForBlueprintUpdates = require('./check-for-blueprint-updates');
const loadSafeDefaultBlueprint = require('./load-safe-default-blueprint');
const loadSafeBlueprint = require('./load-safe-blueprint');
const stageBlueprintFile = require('./stage-blueprint-file');
const getBlueprintFilePath = require('./get-blueprint-file-path');
const isDefaultBlueprint = require('./is-default-blueprint');
const findBlueprint = require('./find-blueprint');

const {
  'to': { default: toDefault },
  'codemods-url': { default: codemodsUrlDefault }
} = require('./args');

function formatBlueprintLine({
  name,
  currentVersion,
  latestVersion
}) {
  return `${name}, current: ${currentVersion}, latest: ${latestVersion}`;
}

module.exports = async function emberCliUpdate({
  blueprint: _blueprint,
  from,
  to,
  resolveConflicts,
  runCodemods,
  codemodsUrl = codemodsUrlDefault,
  codemodsJson,
  reset,
  compareOnly,
  statsOnly,
  listCodemods,
  createCustomDiff,
  wasRunAsExecutable
}) {
  let cwd = process.cwd();

  let emberCliUpdateJson = await loadSafeBlueprintFile(cwd);

  let blueprint;
  let packageUrl;
  let isPersistedBlueprint;

  if (_blueprint) {
    let parsedBlueprint = await parseBlueprint(_blueprint);
    packageUrl = parsedBlueprint.url;

    let { name } = parsedBlueprint;
    if (!name) {
      let downloadedPackage = await downloadPackage(null, packageUrl, toDefault);
      name = downloadedPackage.name;
    }

    let packageName = name;

    let existingBlueprint = findBlueprint(emberCliUpdateJson, packageName, name);
    if (existingBlueprint) {
      isPersistedBlueprint = true;
      blueprint = loadSafeBlueprint(existingBlueprint);
    } else {
      blueprint = loadSafeBlueprint({
        packageName,
        name,
        location: parsedBlueprint.location
      });
    }

    if (from) {
      blueprint.version = from;
    }

    if (!blueprint.version && !reset) {
      throw new Error('A custom blueprint cannot detect --from. You must supply it.');
    }
  } else {
    let { blueprints } = emberCliUpdateJson;

    if (!blueprints.length) {
      blueprint = loadSafeDefaultBlueprint();
    } else {
      isPersistedBlueprint = true;

      let blueprintUpdates = await checkForBlueprintUpdates(blueprints);

      let areAllUpToDate = blueprintUpdates.every(blueprintUpdate => blueprintUpdate.isUpToDate);
      if (areAllUpToDate) {
        return `${blueprintUpdates.map(formatBlueprintLine).join(`
`)}

All blueprints are up-to-date!`;
      }

      let choicesByName = blueprintUpdates.reduce((choices, blueprintUpdate) => {
        let name = formatBlueprintLine(blueprintUpdate);
        choices[name] = {
          blueprintUpdate,
          choice: {
            name,
            disabled: blueprintUpdate.isUpToDate
          }
        };
        return choices;
      }, {});

      let answer = await inquirer.prompt([{
        type: 'list',
        message: 'Blueprint updates have been found. Which one would you like to update?',
        name: 'blueprint',
        choices: Object.values(choicesByName).map(({ choice }) => choice)
      }]);

      let { blueprintUpdate } = choicesByName[answer.blueprint];

      let existingBlueprint = findBlueprint(emberCliUpdateJson, blueprintUpdate.packageName, blueprintUpdate.name);
      blueprint = loadSafeBlueprint(existingBlueprint);
    }
  }

  if (blueprint.location && !packageUrl) {
    packageUrl = (await parseBlueprint(blueprint.location)).url;
  }

  let isCustomBlueprint = !isDefaultBlueprint(blueprint);

  if (isCustomBlueprint) {
    createCustomDiff = true;
  }

  let endBlueprint;

  let result = await (await boilerplateUpdate({
    projectOptions: ({ packageJson }) => getProjectOptions(packageJson, blueprint),
    mergeOptions: async function mergeOptions({
      packageJson,
      projectOptions
    }) {
      if (createCustomDiff && projectOptions.includes('glimmer')) {
        // ember-cli doesn't have a way to use non-latest blueprint versions
        // TODO: The above is not true anymore. This can be fixed.
        throw 'cannot checkout older versions of glimmer blueprint';
      }

      let startVersion;
      let endVersion;
      let startBlueprint;

      if (!isCustomBlueprint && createCustomDiff) {
        blueprint = loadSafeDefaultBlueprint(projectOptions, blueprint.version);
      }

      if (isCustomBlueprint) {
        startBlueprint = { ...blueprint, ...await downloadPackage(blueprint.name, packageUrl, blueprint.version) };
        endBlueprint = { ...blueprint, ...await downloadPackage(blueprint.name, packageUrl, to) };

        startVersion = startBlueprint.version;
        endVersion = endBlueprint.version;
      } else {
        let packageName = getPackageName(projectOptions);
        let packageVersion = getPackageVersion(packageJson, packageName);

        let versions = await getVersions(packageName);

        let getTagVersion = _getTagVersion(versions, packageName);

        if (from) {
          startVersion = await getTagVersion(from);
        } else {
          startVersion = getProjectVersion(packageVersion, versions, projectOptions);
        }

        endVersion = await getTagVersion(to);

        startBlueprint = { ...blueprint, version: startVersion };
        endBlueprint = { ...blueprint, version: endVersion };
      }

      let customDiffOptions;
      if (createCustomDiff) {
        customDiffOptions = getStartAndEndCommands({
          packageJson,
          startBlueprint,
          endBlueprint
        });
      }

      return {
        startVersion,
        endVersion,
        customDiffOptions
      };
    },
    remoteUrl: ({ projectOptions }) => getRemoteUrl(projectOptions),
    compareOnly,
    resolveConflicts,
    reset,
    statsOnly,
    listCodemods,
    runCodemods,
    codemodsUrl,
    codemodsJson,
    createCustomDiff,
    ignoredFiles: [await getBlueprintFilePath(cwd)],
    wasRunAsExecutable
  })).promise;

  if (_blueprint) {
    let emberCliUpdateJson = await loadBlueprintFile(cwd);

    // If you don't have a state file, save the default blueprint,
    // even if you are currently working on a custom blueprint.
    if (!emberCliUpdateJson || !isCustomBlueprint) {
      await saveDefaultBlueprint({
        cwd
      });
    }

    if (isCustomBlueprint) {
      await saveBlueprint({
        cwd,
        blueprint: endBlueprint
      });
    }

    if (!reset) {
      await stageBlueprintFile(cwd);
    }
  } else if (isPersistedBlueprint) {
    await saveBlueprint({
      cwd,
      blueprint: endBlueprint
    });

    if (!reset) {
      await stageBlueprintFile(cwd);
    }
  }

  return result;
};
<|endoftext|>


<commit_before>export { default as GeoSearchControl } from './leafletControl';
export { default as SearchElement } from './searchElement';

export { default as BingProvider } from './providers/bingProvider';
export { default as EsriProvider } from './providers/esriProvider';
export { default as GoogleProvider } from './providers/googleProvider';
export { default as OpenStreetMapProvider } from './providers/openStreetMapProvider';
export { default as AlgoliaProvider } from './algoliaProvider';
export { default as Provider } from './providers/provider';
<commit_msg>Fix import in index.js<commit_after>export { default as GeoSearchControl } from './leafletControl';
export { default as SearchElement } from './searchElement';

export { default as BingProvider } from './providers/bingProvider';
export { default as EsriProvider } from './providers/esriProvider';
export { default as GoogleProvider } from './providers/googleProvider';
export { default as OpenStreetMapProvider } from './providers/openStreetMapProvider';
export { default as AlgoliaProvider } from './providers/algoliaProvider';
export { default as Provider } from './providers/provider';
<|endoftext|>


<commit_before>const request   = require('request');
const NodeCache = require('node-cache');

const cache = new NodeCache();

const baseUrl   = 'https://onionoo.torproject.org/';
const endpoints = [
  'summary',
  'details',
  'bandwidth',
  'weights',
  'clients',
  'uptime'
];

function checkResponseCache(response) {
  const cacheControl = response.headers['cache-control'];
  const maxAgeRegex = /max-age=(\d+)/;
  const maxAge = cacheControl && cacheControl.match(maxAgeRegex);
  return maxAge && maxAge[1];
}

module.exports = endpoints.reduce((onionoo, endpoint) => {
  onionoo[endpoint] = args => new Promise((resolve, reject) => {
    const requestOptions = {
      uri:  `${baseUrl}${endpoint}`,
      qs:   args,
      json: true
    };
    const cacheKey = JSON.stringify(requestOptions);

    const cachedResult = cache.get(cacheKey);
    if(cachedResult) {
      resolve(cachedResult);
    }

    request(requestOptions, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        const ttl = checkResponseCache(response);
        if(ttl) {
          cache.set(cacheKey, body, ttl);
        }
        resolve(body);
      } else {
        reject(error || {
          statusCode: response.statusCode,
          statusMessage: response.statusMessage
        });
      }
    })
  });

  return onionoo;
}, {});
<commit_msg>Accept gzip<commit_after>const request   = require('request');
const NodeCache = require('node-cache');

const cache = new NodeCache();

const baseUrl   = 'https://onionoo.torproject.org/';
const endpoints = [
  'summary',
  'details',
  'bandwidth',
  'weights',
  'clients',
  'uptime'
];

function checkResponseCache(response) {
  const cacheControl = response.headers['cache-control'];
  const maxAgeRegex = /max-age=(\d+)/;
  const maxAge = cacheControl && cacheControl.match(maxAgeRegex);
  return maxAge && maxAge[1];
}

module.exports = endpoints.reduce((onionoo, endpoint) => {
  onionoo[endpoint] = args => new Promise((resolve, reject) => {
    const requestOptions = {
      uri:  `${baseUrl}${endpoint}`,
      qs:   args,
      json: true,
      gzip: true
    };
    const cacheKey = JSON.stringify(requestOptions);

    const cachedResult = cache.get(cacheKey);
    if(cachedResult) {
      resolve(cachedResult);
    }

    request(requestOptions, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        const ttl = checkResponseCache(response);
        if(ttl) {
          cache.set(cacheKey, body, ttl);
        }
        resolve(body);
      } else {
        reject(error || {
          statusCode: response.statusCode,
          statusMessage: response.statusMessage
        });
      }
    })
  });

  return onionoo;
}, {});
<|endoftext|>


<commit_before>
var _                = require('lodash');
var fs               = require('fs');
var moment           = require('moment');

var MailerClass      = require('./mailer');
var PostServerClass  = require('./postServer');
var SpreadsheetClass = require('./spreadsheet');
var S3Class          = require('./s3');

//------------------------------------------------------------------------------
//environment variables
var env = process.env;

var mailgunDomain = env.MAILGUN_DOMAIN;

var inboundMessageEndpoint = env.ENDPOINT_SECRET;

var postServer = new PostServerClass(env.PORT || 5000);

var mailer = new MailerClass({
  apiKey: env.MAILGUN_API_KEY,
  domain: mailgunDomain,
  from: 'Expensa Bot <expensa@' + mailgunDomain + '>',
});

var spreadsheet = new SpreadsheetClass({
  email:  env.GDRIVE_EMAIL,
  fileId: env.GDRIVE_FILEID,
  //fallback to a local file when we are running locally
  key:    env.GDRIVE_KEY || fs.readFileSync(env.GDRIVE_KEYFILE),
});

var s3 = new S3Class({
  accessKeyId:     env.S3_ACCESS_KEY,
  secretAccessKey: env.S3_SECRET_KEY,
  bucket:          env.S3_BUCKET,
});

//------------------------------------------------------------------------------
//main flow
function _messagePosted(url, message){
  //for security only accept posts to the secret endpoint
  if(url !== '/' + inboundMessageEndpoint){
    throw new Error('unexpected url:' + url);
  }

  var parsedMessage = parseMessage(message);

  uploadAttachments(parsedMessage, function(error, uploadedMessage){
    if(error){
      logError(parsedMessage.sender, error)
      return;
    }
    appendMessageToSpreadsheet(uploadedMessage);
    confirmReceipt(uploadedMessage);
  });
}
function messagePosted(url, message){
  try{
    _messagePosted.apply(null, arguments);
  }catch(error){
    logError(message.sender, error);
  }
}

postServer.listen(messagePosted);

//------------------------------------------------------------------------------
function parseMessage(message){
  var category = message.recipient.replace('@' + mailgunDomain, '');

  var parsedSubject = parseSubject(message.subject);

  treatBodyAsAttachment(message);

  return {
    timestamp:   moment().format('D/M/YY h:mma'),
    sender:      message.sender,
    category:    category,
    amount:      parsedSubject.amount,
    description: parsedSubject.description,
    attachments: message.attachments,
  }
}
//split subject into (<amount>:) <description>
function parseSubject(subject){
  var subjectSplit = subject.indexOf(':');
  var description = subject;
  var amount = null;
  if(subjectSplit !== -1){
    amount = subject.slice(0, subjectSplit);
    description = subject.slice(subjectSplit + 1);
  }
  return {
    amount:amount,
    description: description,
  };
}
function treatBodyAsAttachment(message){
  var bodyAttachment;
  if(message['body-html']){
    bodyAttachment = {
      fileName: 'body.html',
      contentType: 'text/html',
      buffer: new Buffer(message['body-html']),
    }
  }else{
    bodyAttachment = {
      fileName: 'body.txt',
      contentType: 'text/plain',
      buffer: new Buffer(message['body-plain']),
    }
  }
  message.attachments.unshift(bodyAttachment);
}

//------------------------------------------------------------------------------
function appendMessageToSpreadsheet(message){
  var row = [
    message.timestamp,
    message.sender,
    message.category,
    message.amount,
    message.description
  ];

  _.each(message.attachments, function(attachmentLink, index){
    var cell = ['=HYPERLINK("', attachmentLink, '", "', index, '")'].join('');
    row.push(cell);
  });
    var errorHook = _.curry(logError)(message.sender);
  spreadsheet.append(row, errorHook);
}

//------------------------------------------------------------------------------
//Upload attachments to s3 and replace them with a link to the file
//note that this approach requires the entire attachment to be in RAM
//that should be fine since emails max out at 25mb and we have 512mb on the
//heroku server
function uploadAttachments(parsedMessage, callback){
  var attachmentCount = parsedMessage.attachments.length;
  var uploadedMessage = _.omit(parsedMessage, 'attachments');
  uploadedMessage.attachments = [];
  function done(error, url){
    if(error){
      callback(error);
      return;
    }
    uploadedMessage.attachments.push(url);
    //done with all uploads
    if(uploadedMessage.attachments.length == attachmentCount){
      callback(null, uploadedMessage);
    }
  }
  var timestamp = new Date().getTime() + '/';
  _.each(parsedMessage.attachments, function(attachment, index){
    var fileName = timestamp + index + '-' + attachment.fileName;
    s3.upload(fileName, attachment.contentType, attachment.buffer, done)
  });
}

//------------------------------------------------------------------------------
//email sender a confirmation of what was done
function confirmReceipt(message){
  var fields  = JSON.stringify(message, null, '    ');
  var receipt = 'The following message has been processed:\n' + fields + '\n';
  receipt    += '--Expensa Bot';
  mailer.send({
    to: message.sender,
    subject: 'Message Processed on ' + message.timestamp,
    text: receipt,
  });
}

//------------------------------------------------------------------------------
//notify user with email 'to' of exception/text 'error'
function logError(to, error){
  if(error.stack){
    error = error.stack;
  }
  console.log('Error:', to, error);
  mailer.send({
    to:      to,
    subject: 'Expensa encountered an unexpected error, try your request again.'
      + '(' + moment().format() + ')',
    text:    error + '',
  });
}
<commit_msg>refactor(index): make error logging wrapper generic<commit_after>
var _                = require('lodash');
var fs               = require('fs');
var moment           = require('moment');

var MailerClass      = require('./mailer');
var PostServerClass  = require('./postServer');
var SpreadsheetClass = require('./spreadsheet');
var S3Class          = require('./s3');

//------------------------------------------------------------------------------
//environment variables
var env = process.env;

var mailgunDomain = env.MAILGUN_DOMAIN;

var inboundMessageEndpoint = env.ENDPOINT_SECRET;

var postServer = new PostServerClass(env.PORT || 5000);

var mailer = new MailerClass({
  apiKey: env.MAILGUN_API_KEY,
  domain: mailgunDomain,
  from: 'Expensa Bot <expensa@' + mailgunDomain + '>',
});

var spreadsheet = new SpreadsheetClass({
  email:  env.GDRIVE_EMAIL,
  fileId: env.GDRIVE_FILEID,
  //fallback to a local file when we are running locally
  key:    env.GDRIVE_KEY || fs.readFileSync(env.GDRIVE_KEYFILE),
});

var s3 = new S3Class({
  accessKeyId:     env.S3_ACCESS_KEY,
  secretAccessKey: env.S3_SECRET_KEY,
  bucket:          env.S3_BUCKET,
});

//------------------------------------------------------------------------------
//main flow
function _messagePosted(url, message){
  //for security only accept posts to the secret endpoint
  if(url !== '/' + inboundMessageEndpoint){
    throw new Error('unexpected url:' + url);
  }

  var parsedMessage = parseMessage(message);

  uploadAttachments(parsedMessage, function(error, uploadedMessage){
    if(error){
      logError(parsedMessage.sender, error)
      return;
    }
    appendMessageToSpreadsheet(uploadedMessage);
    confirmReceipt(uploadedMessage);
  });
}

postServer.listen(logErrorsOver(messagePosted));

//------------------------------------------------------------------------------
function parseMessage(message){
  var category = message.recipient.replace('@' + mailgunDomain, '');

  var parsedSubject = parseSubject(message.subject);

  treatBodyAsAttachment(message);

  return {
    timestamp:   moment().format('D/M/YY h:mma'),
    sender:      message.sender,
    category:    category,
    amount:      parsedSubject.amount,
    description: parsedSubject.description,
    attachments: message.attachments,
  }
}
//split subject into (<amount>:) <description>
function parseSubject(subject){
  var subjectSplit = subject.indexOf(':');
  var description = subject;
  var amount = null;
  if(subjectSplit !== -1){
    amount = subject.slice(0, subjectSplit);
    description = subject.slice(subjectSplit + 1);
  }
  return {
    amount:amount,
    description: description,
  };
}
function treatBodyAsAttachment(message){
  var bodyAttachment;
  if(message['body-html']){
    bodyAttachment = {
      fileName: 'body.html',
      contentType: 'text/html',
      buffer: new Buffer(message['body-html']),
    }
  }else{
    bodyAttachment = {
      fileName: 'body.txt',
      contentType: 'text/plain',
      buffer: new Buffer(message['body-plain']),
    }
  }
  message.attachments.unshift(bodyAttachment);
}

//------------------------------------------------------------------------------
function appendMessageToSpreadsheet(message){
  var row = [
    message.timestamp,
    message.sender,
    message.category,
    message.amount,
    message.description
  ];

  _.each(message.attachments, function(attachmentLink, index){
    var cell = ['=HYPERLINK("', attachmentLink, '", "', index, '")'].join('');
    row.push(cell);
  });
    var errorHook = _.curry(logError)(message.sender);
  spreadsheet.append(row, errorHook);
}

//------------------------------------------------------------------------------
//Upload attachments to s3 and replace them with a link to the file
//note that this approach requires the entire attachment to be in RAM
//that should be fine since emails max out at 25mb and we have 512mb on the
//heroku server
function uploadAttachments(parsedMessage, callback){
  var attachmentCount = parsedMessage.attachments.length;
  var uploadedMessage = _.omit(parsedMessage, 'attachments');
  uploadedMessage.attachments = [];
  function done(error, url){
    if(error){
      callback(error);
      return;
    }
    uploadedMessage.attachments.push(url);
    //done with all uploads
    if(uploadedMessage.attachments.length == attachmentCount){
      callback(null, uploadedMessage);
    }
  }
  var timestamp = new Date().getTime() + '/';
  _.each(parsedMessage.attachments, function(attachment, index){
    var fileName = timestamp + index + '-' + attachment.fileName;
    s3.upload(fileName, attachment.contentType, attachment.buffer, done)
  });
}

//------------------------------------------------------------------------------
//email sender a confirmation of what was done
function confirmReceipt(message){
  var fields  = JSON.stringify(message, null, '    ');
  var receipt = 'The following message has been processed:\n' + fields + '\n';
  receipt    += '--Expensa Bot';
  mailer.send({
    to: message.sender,
    subject: 'Message Processed on ' + message.timestamp,
    text: receipt,
  });
}

//------------------------------------------------------------------------------
//notify user with email 'to' of exception/text 'error'
function logError(to, error){
  if(error.stack){
    error = error.stack;
  }
  console.log('Error:', to, error);
  mailer.send({
    to:      to,
    subject: 'Expensa encountered an unexpected error, try your request again.'
      + '(' + moment().format() + ')',
    text:    error + '',
  });
}

// Return a function that calls 'decorateMe' with the same arguments catching any
// exceptions and piping them to 'logError'
function logErrorsOver(decorateMe){
  return function(){
    try{
      _messagePosted.apply(null, arguments);
    }catch(error){
      logError(message.sender, error);
    }
  }
}
<|endoftext|>


<commit_before>export {Cell} from './cell'
export {default as Dashboard} from './dashboard'
export {Graph} from './graph'
export {Image} from './image'
export {Row} from './row'
export {Value} from './value'
<commit_msg>add text module to exports<commit_after>export {Cell} from './cell'
export {default as Dashboard} from './dashboard'
export {Graph} from './graph'
export {Image} from './image'
export {Row} from './row'
export {Text} from './text'
export {Value} from './value'
<|endoftext|>