<commit_before>
//     react-native-loading-spinner-overlay
//     Copyright (c) 2016- Nick Baugh <niftylettuce@gmail.com>
//     MIT Licensed

// * Author: [@niftylettuce](https://twitter.com/#!/niftylettuce)
// * Source:
// <https://github.com/niftylettuce/react-native-loading-spinner-overlay>

// # react-native-loading-spinner-overlay
//
// <https://github.com/facebook/react-native/issues/2501>
// <https://rnplay.org/apps/1YkBCQ>
// <https://github.com/facebook/react-native/issues/2501>
// <https://github.com/brentvatne/react-native-overlay>
//

import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  Modal,
  ActivityIndicator
} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'transparent',
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0
  },
  background: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    justifyContent: 'center',
    alignItems: 'center'
  },
  textContainer: {
    flex: 1,
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute',
  },
  textContent: {
    top: 80,
    height: 50,
    fontSize: 20,
    fontWeight: 'bold'
  }
});

const SIZES = ['small', 'normal', 'large'];

export default class Spinner extends React.Component {

  constructor(props) {
    super(props);
    this.state = { visible: this.props.visible, textContent: this.props.textContent };
  }

  static propTypes = {
    visible: React.PropTypes.bool,
    cancelable: React.PropTypes.bool,
    textContent: React.PropTypes.string,
    color: React.PropTypes.string,
    size: React.PropTypes.oneOf(SIZES),
    overlayColor: React.PropTypes.string
  };

  static defaultProps = {
    visible: false,
    cancelable: false,
    textContent: "",
    color: 'white',
    size: 'large', // 'normal',
    overlayColor: 'rgba(0, 0, 0, 0.25)'
  };

  close() {
    this.setState({ visible: false });
  }

  componentWillReceiveProps(nextProps) {
    const { visible, textContent } = nextProps;
    this.setState({ visible, textContent });
  }

  _handleOnRequestClose() {
    if (this.props.cancelable) {
      this.close();
    }
  }

  _renderDefaultContent() {
    return (
      <View style={styles.background}>
        <ActivityIndicator
          color={this.props.color}
          size={this.props.size}
          style={{ flex: 1 }}
        />
        <View style={styles.textContainer}>
          <Text style={[styles.textContent, this.props.textStyle]}>{this.state.textContent}</Text>
        </View>
      </View>);
  }

  _renderSpinner() {
    const { visible } = this.state;

    if (!visible)
      return (
        <View />
      );

    const spinner = (
      <View style={[
        styles.container,
        { backgroundColor: this.props.overlayColor }
      ]} key={`spinner_${Date.now()}`}>
        {this.props.children ? this.props.children : this._renderDefaultContent()}
      </View>
    );

    return (
      <Modal
        onRequestClose={() => this._handleOnRequestClose()}
        supportedOrientations={['landscape', 'portrait']}
        transparent
        visible={visible}>
        {spinner}
      </Modal>
    );

  }

  render() {
    return this._renderSpinner();
  }

}
<commit_msg>When the spinner is hidden, hide the stub view. (#49)<commit_after>
//     react-native-loading-spinner-overlay
//     Copyright (c) 2016- Nick Baugh <niftylettuce@gmail.com>
//     MIT Licensed

// * Author: [@niftylettuce](https://twitter.com/#!/niftylettuce)
// * Source:
// <https://github.com/niftylettuce/react-native-loading-spinner-overlay>

// # react-native-loading-spinner-overlay
//
// <https://github.com/facebook/react-native/issues/2501>
// <https://rnplay.org/apps/1YkBCQ>
// <https://github.com/facebook/react-native/issues/2501>
// <https://github.com/brentvatne/react-native-overlay>
//

import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  Modal,
  ActivityIndicator
} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'transparent',
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0
  },
  background: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    justifyContent: 'center',
    alignItems: 'center'
  },
  textContainer: {
    flex: 1,
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute'
  },
  textContent: {
    top: 80,
    height: 50,
    fontSize: 20,
    fontWeight: 'bold'
  }
});

const SIZES = ['small', 'normal', 'large'];

export default class Spinner extends React.Component {

  constructor(props) {
    super(props);
    this.state = { visible: this.props.visible, textContent: this.props.textContent };
  }

  static propTypes = {
    visible: React.PropTypes.bool,
    cancelable: React.PropTypes.bool,
    textContent: React.PropTypes.string,
    color: React.PropTypes.string,
    size: React.PropTypes.oneOf(SIZES),
    overlayColor: React.PropTypes.string
  };

  static defaultProps = {
    visible: false,
    cancelable: false,
    textContent: '',
    color: 'white',
    size: 'large', // 'normal',
    overlayColor: 'rgba(0, 0, 0, 0.25)'
  };

  close() {
    this.setState({ visible: false });
  }

  componentWillReceiveProps(nextProps) {
    const { visible, textContent } = nextProps;
    this.setState({ visible, textContent });
  }

  _handleOnRequestClose() {
    if (this.props.cancelable) {
      this.close();
    }
  }

  _renderDefaultContent() {
    return (
      <View style={styles.background}>
        <ActivityIndicator
          color={this.props.color}
          size={this.props.size}
          style={{ flex: 1 }}
        />
        <View style={styles.textContainer}>
          <Text style={[styles.textContent, this.props.textStyle]}>{this.state.textContent}</Text>
        </View>
      </View>);
  }

  _renderSpinner() {
    const { visible } = this.state;

    if (!visible)
      return (
        <View display="none" />
      );

    const spinner = (
      <View style={[
        styles.container,
        { backgroundColor: this.props.overlayColor }
      ]} key={`spinner_${Date.now()}`}>
        {this.props.children ? this.props.children : this._renderDefaultContent()}
      </View>
    );

    return (
      <Modal
        onRequestClose={() => this._handleOnRequestClose()}
        supportedOrientations={['landscape', 'portrait']}
        transparent
        visible={visible}>
        {spinner}
      </Modal>
    );

  }

  render() {
    return this._renderSpinner();
  }

}
<|endoftext|>


<commit_before>/* @flow */

import { MongodHelper } from 'mongodb-prebuilt';
import uuid from 'uuid/v4';
import tmp from 'tmp';
import getport from 'get-port';

tmp.setGracefulCleanup();

export type MongoMemoryServerOptsT = {
  port?: ?number,
  storageEngine?: string,
  dbPath?: string,
  autoStart?: boolean,
  debug?: boolean,
};

export type MongoInstanceDataT = {
  port: number,
  dbPath: string,
  uri: string,
  storageEngine: string,
  mongodCli: MongodHelper,
  tmpDir?: {
    name: string,
    removeCallback: Function,
  },
};

async function generateConnectionString(port: number, dbName: ?string): Promise<string> {
  const db = dbName || (await uuid());
  return `mongodb://localhost:${port}/${db}`;
}

export default class MongoDBMemoryServer {
  isRunning: boolean = false;
  runningInstance: ?Promise<MongoInstanceDataT>;
  opts: MongoMemoryServerOptsT;

  constructor(opts?: MongoMemoryServerOptsT = {}) {
    this.opts = opts;

    // autoStart by default
    if (!opts.hasOwnProperty('autoStart') || opts.autoStart) {
      if (opts.debug) {
        console.log('Autostarting MongoDB instance...');
      }
      this.start();
    }
  }

  debug(msg: string) {
    if (this.opts.debug) {
      console.log(msg);
    }
  }

  async start(): Promise<boolean> {
    if (this.runningInstance) {
      throw new Error(
        'MongoDB instance already in status startup/running/error. Use opts.debug = true for more info.'
      );
    }

    this.runningInstance = this._startUpInstance()
      .catch(err => {
        if (err.message === 'Mongod shutting down' || err === 'Mongod shutting down') {
          this.debug(`Mongodb does not started. Trying to start on another port one more time...`);
          this.opts.port = null;
          return this._startUpInstance();
        }
        throw err;
      })
      .catch(err => {
        if (!this.opts.debug) {
          throw new Error(
            `${err.message}\n\nUse debug option for more info: new MongoMemoryServer({ debug: true })`
          );
        }
        throw err;
      });

    return this.runningInstance.then(() => true);
  }

  async _startUpInstance(): Promise<MongoInstanceDataT> {
    const data = {};
    let tmpDir;

    data.port = await getport(this.opts.port);
    data.uri = await generateConnectionString(data.port);
    data.storageEngine = this.opts.storageEngine || 'ephemeralForTest';
    if (this.opts.dbPath) {
      data.dbPath = this.opts.dbPath;
    } else {
      tmpDir = tmp.dirSync({ prefix: 'mongo-mem-', unsafeCleanup: true });
      data.dbPath = tmpDir.name;
    }

    this.debug(`Starting MongoDB instance with following options: ${JSON.stringify(data)}`);

    const mongodCli = new MongodHelper([
      '--port',
      data.port,
      '--storageEngine',
      data.storageEngine,
      '--dbpath',
      data.dbPath,
      '--noauth',
    ]);

    mongodCli.debug.enabled = this.opts.debug;

    // Download if not exists mongo binaries in ~/.mongodb-prebuilt
    // After that startup MongoDB instance
    await mongodCli.run();

    data.mongodCli = mongodCli;
    data.tmpDir = tmpDir;

    return data;
  }

  async stop(): Promise<boolean> {
    const { mongodCli, port, tmpDir } = (await this.getInstanceData(): MongoInstanceDataT);

    if (mongodCli && mongodCli.mongoBin.childProcess) {
      // .mongoBin.childProcess.connected
      this.debug(
        `Shutdown MongoDB server on port ${port} with pid ${mongodCli.mongoBin.childProcess.pid}`
      );
      mongodCli.mongoBin.childProcess.kill();
    }

    if (tmpDir) {
      this.debug(`Removing tmpDir ${tmpDir.name}`);
      tmpDir.removeCallback();
    }

    this.runningInstance = null;
    return true;
  }

  async getInstanceData(): Promise<MongoInstanceDataT> {
    if (this.runningInstance) {
      return this.runningInstance;
    }
    throw new Error(
      'Database instance is not running. You should start database by calling start() method. BTW it should start automatically if opts.autoStart!=false. Also you may provide opts.debug=true for more info.'
    );
  }

  async getUri(otherDbName?: string | boolean = false): Promise<string> {
    const { uri, port } = (await this.getInstanceData(): MongoInstanceDataT);

    // IF true OR string
    if (otherDbName) {
      if (typeof otherDbName === 'string') {
        // generate uri with provided DB name on existed DB instance
        return generateConnectionString(port, otherDbName);
      }
      // generate new random db name
      return generateConnectionString(port);
    }

    return uri;
  }

  async getConnectionString(otherDbName: string | boolean = false): Promise<string> {
    return this.getUri(otherDbName);
  }

  async getPort(): Promise<number> {
    const { port } = (await this.getInstanceData(): MongoInstanceDataT);
    return port;
  }

  async getDbPath(): Promise<string> {
    const { dbPath } = (await this.getInstanceData(): MongoInstanceDataT);
    return dbPath;
  }
}
<commit_msg>fix(Concurrency): Multiple databases start ups in serial.<commit_after>/* @flow */

import { MongodHelper } from 'mongodb-prebuilt';
import uuid from 'uuid/v4';
import tmp from 'tmp';
import getport from 'get-port';

tmp.setGracefulCleanup();

export type MongoMemoryServerOptsT = {
  port?: ?number,
  storageEngine?: string,
  dbPath?: string,
  autoStart?: boolean,
  debug?: boolean,
};

export type MongoInstanceDataT = {
  port: number,
  dbPath: string,
  uri: string,
  storageEngine: string,
  mongodCli: MongodHelper,
  tmpDir?: {
    name: string,
    removeCallback: Function,
  },
};

async function generateConnectionString(port: number, dbName: ?string): Promise<string> {
  const db = dbName || (await uuid());
  return `mongodb://localhost:${port}/${db}`;
}

export default class MongoDBMemoryServer {
  static mongodHelperStartup: ?Promise<any>;
  isRunning: boolean = false;
  runningInstance: ?Promise<MongoInstanceDataT>;
  opts: MongoMemoryServerOptsT;

  constructor(opts?: MongoMemoryServerOptsT = {}) {
    this.opts = opts;

    // autoStart by default
    if (!opts.hasOwnProperty('autoStart') || opts.autoStart) {
      if (opts.debug) {
        console.log('Autostarting MongoDB instance...');
      }
      this.start();
    }
  }

  debug(msg: string) {
    if (this.opts.debug) {
      console.log(msg);
    }
  }

  async start(): Promise<boolean> {
    if (this.runningInstance) {
      throw new Error(
        'MongoDB instance already in status startup/running/error. Use opts.debug = true for more info.'
      );
    }

    this.runningInstance = this._startUpInstance()
      .catch(err => {
        if (err.message === 'Mongod shutting down' || err === 'Mongod shutting down') {
          this.debug(`Mongodb does not started. Trying to start on another port one more time...`);
          this.opts.port = null;
          return this._startUpInstance();
        }
        throw err;
      })
      .catch(err => {
        if (!this.opts.debug) {
          throw new Error(
            `${err.message}\n\nUse debug option for more info: new MongoMemoryServer({ debug: true })`
          );
        }
        throw err;
      });

    return this.runningInstance.then(() => true);
  }

  async _startUpInstance(): Promise<MongoInstanceDataT> {
    const data = {};
    let tmpDir;

    data.port = await getport(this.opts.port);
    data.uri = await generateConnectionString(data.port);
    data.storageEngine = this.opts.storageEngine || 'ephemeralForTest';
    if (this.opts.dbPath) {
      data.dbPath = this.opts.dbPath;
    } else {
      tmpDir = tmp.dirSync({ prefix: 'mongo-mem-', unsafeCleanup: true });
      data.dbPath = tmpDir.name;
    }

    this.debug(`Starting MongoDB instance with following options: ${JSON.stringify(data)}`);

    const mongodCli = new MongodHelper([
      '--port',
      data.port,
      '--storageEngine',
      data.storageEngine,
      '--dbpath',
      data.dbPath,
      '--noauth',
    ]);

    mongodCli.debug.enabled = this.opts.debug;

    if (this.constructor.mongodHelperStartup) {
      await this.constructor.mongodHelperStartup;
    }

    // Download if not exists mongo binaries in ~/.mongodb-prebuilt
    // After that startup MongoDB instance
    const startupPromise = mongodCli.run();
    this.constructor.mongodHelperStartup = startupPromise;
    await startupPromise;

    data.mongodCli = mongodCli;
    data.tmpDir = tmpDir;

    return data;
  }

  async stop(): Promise<boolean> {
    const { mongodCli, port, tmpDir } = (await this.getInstanceData(): MongoInstanceDataT);

    if (mongodCli && mongodCli.mongoBin.childProcess) {
      // .mongoBin.childProcess.connected
      this.debug(
        `Shutdown MongoDB server on port ${port} with pid ${mongodCli.mongoBin.childProcess.pid}`
      );
      mongodCli.mongoBin.childProcess.kill();
    }

    if (tmpDir) {
      this.debug(`Removing tmpDir ${tmpDir.name}`);
      tmpDir.removeCallback();
    }

    this.runningInstance = null;
    return true;
  }

  async getInstanceData(): Promise<MongoInstanceDataT> {
    if (this.runningInstance) {
      return this.runningInstance;
    }
    throw new Error(
      'Database instance is not running. You should start database by calling start() method. BTW it should start automatically if opts.autoStart!=false. Also you may provide opts.debug=true for more info.'
    );
  }

  async getUri(otherDbName?: string | boolean = false): Promise<string> {
    const { uri, port } = (await this.getInstanceData(): MongoInstanceDataT);

    // IF true OR string
    if (otherDbName) {
      if (typeof otherDbName === 'string') {
        // generate uri with provided DB name on existed DB instance
        return generateConnectionString(port, otherDbName);
      }
      // generate new random db name
      return generateConnectionString(port);
    }

    return uri;
  }

  async getConnectionString(otherDbName: string | boolean = false): Promise<string> {
    return this.getUri(otherDbName);
  }

  async getPort(): Promise<number> {
    const { port } = (await this.getInstanceData(): MongoInstanceDataT);
    return port;
  }

  async getDbPath(): Promise<string> {
    const { dbPath } = (await this.getInstanceData(): MongoInstanceDataT);
    return dbPath;
  }
}
<|endoftext|>


<commit_before>
import { Select } from './query'

const builder = {

  /**
   *
   * @returns {Select}
   */
  select() {
    return new Select().select(...arguments)
  },

  /**
   *
   * @return {Select}
   */
  selectFrom() {
    return this.select().from(...arguments)
  }

}

// export helpers
export * from './helpers'

export default builder<commit_msg>Add missing query builder methods<commit_after>
import { Select, Insert, Delete, Update } from './query'

const builder = {

  /**
   *
   * @param {Any} value
   * @returns {Select}
   */
  select(...value) {
    return new Select().setColumns(value)
  },

  /**
   *
   * @param {Any} value
   * @return {Select}
   */
  selectFrom(...value) {
    return this.select().setTables(value)
  },

  /**
   *
   * @param {Object|Array} data
   * @returns {Insert}
   */
  insert(data) {
    return new Insert().values(data)
  },

  /**
   *
   * @param {String|Expression} table
   * @param {String|Expression} columns
   * @returns {Insert}
   */
  insertInto(table, ...columns) {
    return new Insert().into(table, ...columns)
  },

  /**
   *
   * @param {String|Expression} table
   * @returns {Update}
   */
  update(table) {
    return new Update().setTable(table)
  },

  /**
   *
   * @param {String|Expression} table
   * @returns {Delete}
   */
  deleteFrom(table) {
    return new Delete().setTable(table)
  },

  /**
   *
   * @see deleteFrom()
   */
  delete(table) {
    return this.deleteFrom(table)
  }

}

// export helpers
export * from './helpers'

export default builder<|endoftext|>


<commit_before>/**
 * @module serverless-plugin-warmup
 *
 * @see {@link https://serverless.com/framework/docs/providers/aws/guide/plugins/}
 *
 * @requires 'fs-extra'
 * @requires 'path'
 * */
const fs = require('fs-extra');
const path = require('path');

/**
 * @classdesc Keep your lambdas warm during winter
 * @class WarmUp
 * */
class WarmUp {
  /**
   * @description Serverless Warm Up
   * @constructor
   *
   * @param {!Object} serverless - Serverless object
   * @param {!Object} options - Serverless options
   * */
  constructor(serverless, options) {
    /** Serverless variables */
    this.serverless = serverless;
    this.options = options;

    this.provider = this.serverless.getProvider('aws');

    this.hooks = {
      'after:package:initialize': this.afterPackageInitialize.bind(this),
      'after:package:createDeploymentArtifacts': this.afterCreateDeploymentArtifacts.bind(this),
      'after:deploy:deploy': this.afterDeployFunctions.bind(this),
    };
  }

  /**
   * @description After package initialize hook. Create warmer function and add it to the service.
   *
   * @fulfil {} — Warm up set
   * @reject {Error} Warm up error
   *
   * @return {Promise}
   * */
  async afterPackageInitialize() {
    this.resolvedOptions = this.getResolvedStageAndRegion();
    this.warmupOpts = this.configPlugin(this.serverless.service, this.resolvedOptions.stage);
    this.functionsToWarmup = WarmUp.getFunctionsToBeWarmedUp(
      this.serverless.service,
      this.resolvedOptions.stage,
      this.warmupOpts,
    );

    if (!this.functionsToWarmup.length) {
      this.serverless.cli.log('WarmUp: no functions to warm up');
      return;
    }

    await this.createWarmUpFunctionArtifact(
      this.functionsToWarmup,
      this.resolvedOptions.region,
      this.warmupOpts.pathFile,
    );
    WarmUp.addWarmUpFunctionToService(this.serverless.service, this.warmupOpts);
  }

  /**
   * @description After create deployment artifacts. Clean prefix folder.
   *
   * @fulfil {} — Optimization finished
   * @reject {Error} Optimization error
   *
   * @return {Promise}
   * */
  async afterCreateDeploymentArtifacts() {
    this.resolvedOptions = this.resolvedOptions || this.getResolvedStageAndRegion();
    this.warmupOpts = this.warmupOpts
      || this.configPlugin(this.serverless.service, this.resolvedOptions.stage);
    if (this.warmupOpts.cleanFolder) {
      await this.cleanFolder();
    }
  }

  /**
   * @description After deploy functions hooks
   *
   * @fulfil {} — Functions warmed up sucessfuly
   * @reject {Error} Functions couldn't be warmed up
   *
   * @return {Promise}
   * */
  async afterDeployFunctions() {
    this.resolvedOptions = this.resolvedOptions || this.getResolvedStageAndRegion();
    this.warmupOpts = this.warmupOpts
      || this.configPlugin(this.serverless.service, this.resolvedOptions.stage);
    if (this.warmupOpts.prewarm) {
      this.functionsToWarmup = this.functionsToWarmup || WarmUp.getFunctionsToBeWarmedUp(
        this.serverless.service,
        this.resolvedOptions.stage,
        this.warmupOpts,
      );

      if (this.functionsToWarmup.length <= 0) {
        this.serverless.cli.log('WarmUp: no functions to prewarm');
        return;
      }

      WarmUp.addWarmUpFunctionToService(this.serverless.service, this.warmupOpts);
      await this.warmUpFunctions(this.serverless.service, this.warmupOpts);
    }
  }

  /**
   * @description Get the stage and region properly resolved
   * See https://github.com/serverless/serverless/issues/2631
   *
   * @return {Object} - Stage and region options
   * */
  getResolvedStageAndRegion() {
    return {
      stage: this.options.stage
        || this.serverless.service.provider.stage
        || (this.serverless.service.defaults && this.serverless.service.defaults.stage)
        || 'dev',
      region: this.options.region
        || this.serverless.service.provider.region
        || (this.serverless.service.defaults && this.serverless.service.defaults.region)
        || 'us-east-1',
    };
  }

  /**
   * @description Clean a global configuration object
   * and fill the missing options using the given defaults
   *
   * @return {Object} - Global configuration options
   * */
  getGlobalConfig(possibleConfig, defaultOpts) {
    const config = (typeof possibleConfig === 'object') ? possibleConfig : {};
    const folderName = (typeof config.folderName === 'string') ? config.folderName : '_warmup';
    const pathFolder = path.join(this.serverless.config.servicePath, folderName);

    /* eslint-disable no-nested-ternary */
    // Keep backwards compatibility for now
    config.events = (typeof config.schedule === 'string')
      ? [{ schedule: config.schedule }]
      : (Array.isArray(config.schedule))
        ? config.schedule.map((schedule) => ({ schedule }))
        : config.events;

    return {
      folderName,
      pathFolder,
      pathFile: path.join(pathFolder, 'index.js'),
      pathHandler: `${folderName}/index.warmUp`,
      cleanFolder: (typeof config.cleanFolder === 'boolean') ? config.cleanFolder : defaultOpts.cleanFolder,
      name: (config.name !== undefined) ? config.name : defaultOpts.name,
      role: (config.role !== undefined) ? config.role : defaultOpts.role,
      tags: (config.tags !== undefined) ? config.tags : defaultOpts.tags,
      vpc: config.vpc === false ? { securityGroupIds: [], subnetIds: [] }
        : (config.vpc !== undefined ? config.vpc : defaultOpts.vpc),
      events: (Array.isArray(config.events)) ? config.events : defaultOpts.events,
      package: typeof config.package === 'object'
        ? {
          individually: (config.package.individually !== undefined)
            ? config.package.individually
            : defaultOpts.package.individually,
          exclude: Array.isArray(config.package.exclude)
            ? config.package.exclude
            : defaultOpts.package.exclude,
          include: Array.isArray(config.package.include)
            ? (config.package.include.includes(`${folderName}/**`)
              ? config.package.include
              : config.package.include.concat([`${folderName}/**`]))
            : [`${folderName}/**`],
        }
        : Object.assign(defaultOpts.package, { include: [`${folderName}/**`] }),
      memorySize: (config.memorySize !== undefined) ? config.memorySize : defaultOpts.memorySize,
      timeout: (config.timeout !== undefined) ? config.timeout : defaultOpts.timeout,
      environment: (config.environment !== undefined)
        ? config.environment
        : defaultOpts.environment,
      prewarm: (config.prewarm !== undefined) ? config.prewarm : defaultOpts.prewarm,
    };
    /* eslint-enable no-nested-ternary */
  }

  /**
   * @description Clean a function-specific configuration object
   * and fill the missing options using the given defaults
   *
   * @return {Object} - Function-specific configuration options
   * */
  static getFunctionConfig(possibleConfig, defaultOpts) {
    const config = (['boolean', 'string'].includes(typeof possibleConfig) || Array.isArray(possibleConfig))
      ? { enabled: possibleConfig }
      : (possibleConfig || {});

    // Keep backwards compatibility for now
    if (config.default) {
      config.enabled = possibleConfig.default;
    }
    if (config.source) {
      config.payload = possibleConfig.source;
    }
    if (config.sourceRaw) {
      config.payloadRaw = config.sourceRaw;
    }

    /* eslint-disable no-nested-ternary */
    return {
      enabled: (config.enabled !== undefined)
        ? config.enabled
        : defaultOpts.enabled,
      payload: (config.payload !== undefined)
        ? (config.payloadRaw ? config.payload : JSON.stringify(config.payload))
        : defaultOpts.payload,
      concurrency: (config.concurrency !== undefined)
        ? config.concurrency
        : defaultOpts.concurrency,
    };
    /* eslint-enable no-nested-ternary */
  }

  /**
   * @description Configure the plugin based on the context of serverless.yml
   *
   * @return {Object} - Configuration options to be used by the plugin
   * */
  configPlugin(service, stage) {
    const globalDefaultOpts = {
      folderName: '_warmup',
      cleanFolder: true,
      memorySize: 128,
      name: `${service.service}-${stage}-warmup-plugin`,
      events: [{ schedule: 'rate(5 minutes)' }],
      package: {
        individually: true,
        exclude: ['**'],
      },
      timeout: 10,
      environment: Object.keys(service.provider.environment || [])
        .reduce((obj, k) => ({ ...obj, [k]: undefined }), {}),
      prewarm: false,
    };

    const functionDefaultOpts = {
      enabled: false,
      payload: JSON.stringify({ source: 'serverless-plugin-warmup' }),
      concurrency: 1,
    };

    const customConfig = service.custom ? service.custom.warmup : undefined;

    return Object.assign(
      this.getGlobalConfig(customConfig, globalDefaultOpts),
      WarmUp.getFunctionConfig(customConfig, functionDefaultOpts),
    );
  }

  /**
   * @description After package initialize hook. Create warmer function and add it to the service.
   *
   * @return {Array} - List of functions to be warmed up and their specific configs
   * */
  static getFunctionsToBeWarmedUp(service, stage, warmupOpts) {
    return service.getAllFunctions()
      .map((name) => service.getFunction(name))
      .map((config) => ({
        name: config.name,
        config: WarmUp.getFunctionConfig(config.warmup, warmupOpts),
      }))
      .filter(({ config: { enabled } }) => (
        enabled === true
        || enabled === 'true'
        || enabled === stage
        || (Array.isArray(enabled) && enabled.indexOf(stage) !== -1)
      ));
  }

  /**
   * @description Clean prefix folder
   *
   * @fulfil {} — Folder cleaned
   * @reject {Error} File system error
   *
   * @return {Promise}
   * */
  async cleanFolder() {
    return fs.remove(this.warmupOpts.pathFolder);
  }

  /**
   * @description Write warm up ES6 function
   *
   * @param {Array} functions - Functions to be warmed up
   *
   * @fulfil {} — Warm up function created
   * @reject {Error} Warm up error
   *
   * @return {Promise}
   * */
  async createWarmUpFunctionArtifact(functions, region, pathFile) {
    /** Log warmup start */
    this.serverless.cli.log(`WarmUp: setting ${functions.length} lambdas to be warm`);

    /** Log functions being warmed up */
    functions.forEach((func) => this.serverless.cli.log(`WarmUp: ${func.name}`));

    const warmUpFunction = `"use strict";

/** Generated by Serverless WarmUp Plugin at ${new Date().toISOString()} */
const aws = require("aws-sdk");
aws.config.region = "${region}";
const lambda = new aws.Lambda();
const functions = ${JSON.stringify(functions)};

module.exports.warmUp = async (event, context) => {
  console.log("Warm Up Start");

  const invokes = await Promise.all(functions.map(async (func) => {
    let concurrency;
    const functionConcurrency = process.env["WARMUP_CONCURRENCY_" + func.name.toUpperCase().replace(/-/g, '_')]

    if (functionConcurrency) {
      concurrency = parseInt(functionConcurrency);
      console.log(\`Warming up function: \${func.name} with concurrency: \${concurrency} (from function-specific environment variable)\`);
    } else if (process.env.WARMUP_CONCURRENCY) {
      concurrency = parseInt(process.env.WARMUP_CONCURRENCY);
      console.log(\`Warming up function: \${func.name} with concurrency: \${concurrency} (from global environment variable)\`);
    } else {
      concurrency = parseInt(func.config.concurrency);
      console.log(\`Warming up function: \${func.name} with concurrency: \${concurrency}\`);
    }

    const params = {
      ClientContext: Buffer.from(\`{"custom":\${func.config.payload}}\`).toString('base64'),
      FunctionName: func.name,
      InvocationType: "RequestResponse",
      LogType: "None",
      Qualifier: process.env.SERVERLESS_ALIAS || "$LATEST",
      Payload: func.config.payload
    };

    try {
      await Promise.all(Array(concurrency).fill(0).map(async () => await lambda.invoke(params).promise()));
      console.log(\`Warm Up Invoke Success: \${func.name}\`);
      return true;
    } catch (e) {
      console.log(\`Warm Up Invoke Error: \${func.name}\`, e);
      return false;
    }
  }));

  console.log(\`Warm Up Finished with \${invokes.filter(r => !r).length} invoke errors\`);
}`;

    /** Write warm up file */
    return fs.outputFile(pathFile, warmUpFunction);
  }

  /**
   * @description Add warm up function to service
   * */
  static addWarmUpFunctionToService(service, warmupOpts) {
    /** SLS warm up function */
    // eslint-disable-next-line no-param-reassign
    service.functions.warmUpPlugin = {
      description: 'Serverless WarmUp Plugin',
      events: warmupOpts.events,
      handler: warmupOpts.pathHandler,
      memorySize: warmupOpts.memorySize,
      name: warmupOpts.name,
      runtime: 'nodejs12.x',
      package: warmupOpts.package,
      timeout: warmupOpts.timeout,
      ...(Object.keys(warmupOpts.environment).length
        ? { environment: warmupOpts.environment }
        : {}),
      ...(warmupOpts.role ? { role: warmupOpts.role } : {}),
      ...(warmupOpts.tags ? { tags: warmupOpts.tags } : {}),
      ...(warmupOpts.vpc ? { vpc: warmupOpts.vpc } : {}),
    };
  }

  /**
   * @description Warm up the functions immediately after deployment
   *
   * @fulfil {} — Functions warmed up successfully
   * @reject {Error} Functions couldn't be warmed up
   *
   * @return {Promise}
   * */
  async warmUpFunctions(service, warmupOpts) {
    this.serverless.cli.log('WarmUp: Pre-warming up your functions');

    try {
      const { SERVERLESS_ALIAS } = service.getFunction('warmUpPlugin').environment || {};
      const params = {
        FunctionName: warmupOpts.name,
        InvocationType: 'RequestResponse',
        LogType: 'None',
        Qualifier: SERVERLESS_ALIAS || '$LATEST',
        Payload: warmupOpts.payload,
      };

      await this.provider.request('Lambda', 'invoke', params);
      this.serverless.cli.log('WarmUp: Functions successfully pre-warmed');
    } catch (err) {
      this.serverless.cli.log('WarmUp: Error while pre-warming functions', err);
    }
  }
}

/** Export WarmUp class */
module.exports = WarmUp;
<commit_msg>Use always single quotes in generated lambda<commit_after>/**
 * @module serverless-plugin-warmup
 *
 * @see {@link https://serverless.com/framework/docs/providers/aws/guide/plugins/}
 *
 * @requires 'fs-extra'
 * @requires 'path'
 * */
const fs = require('fs-extra');
const path = require('path');

/**
 * @classdesc Keep your lambdas warm during winter
 * @class WarmUp
 * */
class WarmUp {
  /**
   * @description Serverless Warm Up
   * @constructor
   *
   * @param {!Object} serverless - Serverless object
   * @param {!Object} options - Serverless options
   * */
  constructor(serverless, options) {
    /** Serverless variables */
    this.serverless = serverless;
    this.options = options;

    this.provider = this.serverless.getProvider('aws');

    this.hooks = {
      'after:package:initialize': this.afterPackageInitialize.bind(this),
      'after:package:createDeploymentArtifacts': this.afterCreateDeploymentArtifacts.bind(this),
      'after:deploy:deploy': this.afterDeployFunctions.bind(this),
    };
  }

  /**
   * @description After package initialize hook. Create warmer function and add it to the service.
   *
   * @fulfil {} — Warm up set
   * @reject {Error} Warm up error
   *
   * @return {Promise}
   * */
  async afterPackageInitialize() {
    this.resolvedOptions = this.getResolvedStageAndRegion();
    this.warmupOpts = this.configPlugin(this.serverless.service, this.resolvedOptions.stage);
    this.functionsToWarmup = WarmUp.getFunctionsToBeWarmedUp(
      this.serverless.service,
      this.resolvedOptions.stage,
      this.warmupOpts,
    );

    if (!this.functionsToWarmup.length) {
      this.serverless.cli.log('WarmUp: no functions to warm up');
      return;
    }

    await this.createWarmUpFunctionArtifact(
      this.functionsToWarmup,
      this.resolvedOptions.region,
      this.warmupOpts.pathFile,
    );
    WarmUp.addWarmUpFunctionToService(this.serverless.service, this.warmupOpts);
  }

  /**
   * @description After create deployment artifacts. Clean prefix folder.
   *
   * @fulfil {} — Optimization finished
   * @reject {Error} Optimization error
   *
   * @return {Promise}
   * */
  async afterCreateDeploymentArtifacts() {
    this.resolvedOptions = this.resolvedOptions || this.getResolvedStageAndRegion();
    this.warmupOpts = this.warmupOpts
      || this.configPlugin(this.serverless.service, this.resolvedOptions.stage);
    if (this.warmupOpts.cleanFolder) {
      await this.cleanFolder();
    }
  }

  /**
   * @description After deploy functions hooks
   *
   * @fulfil {} — Functions warmed up sucessfuly
   * @reject {Error} Functions couldn't be warmed up
   *
   * @return {Promise}
   * */
  async afterDeployFunctions() {
    this.resolvedOptions = this.resolvedOptions || this.getResolvedStageAndRegion();
    this.warmupOpts = this.warmupOpts
      || this.configPlugin(this.serverless.service, this.resolvedOptions.stage);
    if (this.warmupOpts.prewarm) {
      this.functionsToWarmup = this.functionsToWarmup || WarmUp.getFunctionsToBeWarmedUp(
        this.serverless.service,
        this.resolvedOptions.stage,
        this.warmupOpts,
      );

      if (this.functionsToWarmup.length <= 0) {
        this.serverless.cli.log('WarmUp: no functions to prewarm');
        return;
      }

      WarmUp.addWarmUpFunctionToService(this.serverless.service, this.warmupOpts);
      await this.warmUpFunctions(this.serverless.service, this.warmupOpts);
    }
  }

  /**
   * @description Get the stage and region properly resolved
   * See https://github.com/serverless/serverless/issues/2631
   *
   * @return {Object} - Stage and region options
   * */
  getResolvedStageAndRegion() {
    return {
      stage: this.options.stage
        || this.serverless.service.provider.stage
        || (this.serverless.service.defaults && this.serverless.service.defaults.stage)
        || 'dev',
      region: this.options.region
        || this.serverless.service.provider.region
        || (this.serverless.service.defaults && this.serverless.service.defaults.region)
        || 'us-east-1',
    };
  }

  /**
   * @description Clean a global configuration object
   * and fill the missing options using the given defaults
   *
   * @return {Object} - Global configuration options
   * */
  getGlobalConfig(possibleConfig, defaultOpts) {
    const config = (typeof possibleConfig === 'object') ? possibleConfig : {};
    const folderName = (typeof config.folderName === 'string') ? config.folderName : '_warmup';
    const pathFolder = path.join(this.serverless.config.servicePath, folderName);

    /* eslint-disable no-nested-ternary */
    // Keep backwards compatibility for now
    config.events = (typeof config.schedule === 'string')
      ? [{ schedule: config.schedule }]
      : (Array.isArray(config.schedule))
        ? config.schedule.map((schedule) => ({ schedule }))
        : config.events;

    return {
      folderName,
      pathFolder,
      pathFile: path.join(pathFolder, 'index.js'),
      pathHandler: `${folderName}/index.warmUp`,
      cleanFolder: (typeof config.cleanFolder === 'boolean') ? config.cleanFolder : defaultOpts.cleanFolder,
      name: (config.name !== undefined) ? config.name : defaultOpts.name,
      role: (config.role !== undefined) ? config.role : defaultOpts.role,
      tags: (config.tags !== undefined) ? config.tags : defaultOpts.tags,
      vpc: config.vpc === false ? { securityGroupIds: [], subnetIds: [] }
        : (config.vpc !== undefined ? config.vpc : defaultOpts.vpc),
      events: (Array.isArray(config.events)) ? config.events : defaultOpts.events,
      package: typeof config.package === 'object'
        ? {
          individually: (config.package.individually !== undefined)
            ? config.package.individually
            : defaultOpts.package.individually,
          exclude: Array.isArray(config.package.exclude)
            ? config.package.exclude
            : defaultOpts.package.exclude,
          include: Array.isArray(config.package.include)
            ? (config.package.include.includes(`${folderName}/**`)
              ? config.package.include
              : config.package.include.concat([`${folderName}/**`]))
            : [`${folderName}/**`],
        }
        : Object.assign(defaultOpts.package, { include: [`${folderName}/**`] }),
      memorySize: (config.memorySize !== undefined) ? config.memorySize : defaultOpts.memorySize,
      timeout: (config.timeout !== undefined) ? config.timeout : defaultOpts.timeout,
      environment: (config.environment !== undefined)
        ? config.environment
        : defaultOpts.environment,
      prewarm: (config.prewarm !== undefined) ? config.prewarm : defaultOpts.prewarm,
    };
    /* eslint-enable no-nested-ternary */
  }

  /**
   * @description Clean a function-specific configuration object
   * and fill the missing options using the given defaults
   *
   * @return {Object} - Function-specific configuration options
   * */
  static getFunctionConfig(possibleConfig, defaultOpts) {
    const config = (['boolean', 'string'].includes(typeof possibleConfig) || Array.isArray(possibleConfig))
      ? { enabled: possibleConfig }
      : (possibleConfig || {});

    // Keep backwards compatibility for now
    if (config.default) {
      config.enabled = possibleConfig.default;
    }
    if (config.source) {
      config.payload = possibleConfig.source;
    }
    if (config.sourceRaw) {
      config.payloadRaw = config.sourceRaw;
    }

    /* eslint-disable no-nested-ternary */
    return {
      enabled: (config.enabled !== undefined)
        ? config.enabled
        : defaultOpts.enabled,
      payload: (config.payload !== undefined)
        ? (config.payloadRaw ? config.payload : JSON.stringify(config.payload))
        : defaultOpts.payload,
      concurrency: (config.concurrency !== undefined)
        ? config.concurrency
        : defaultOpts.concurrency,
    };
    /* eslint-enable no-nested-ternary */
  }

  /**
   * @description Configure the plugin based on the context of serverless.yml
   *
   * @return {Object} - Configuration options to be used by the plugin
   * */
  configPlugin(service, stage) {
    const globalDefaultOpts = {
      folderName: '_warmup',
      cleanFolder: true,
      memorySize: 128,
      name: `${service.service}-${stage}-warmup-plugin`,
      events: [{ schedule: 'rate(5 minutes)' }],
      package: {
        individually: true,
        exclude: ['**'],
      },
      timeout: 10,
      environment: Object.keys(service.provider.environment || [])
        .reduce((obj, k) => ({ ...obj, [k]: undefined }), {}),
      prewarm: false,
    };

    const functionDefaultOpts = {
      enabled: false,
      payload: JSON.stringify({ source: 'serverless-plugin-warmup' }),
      concurrency: 1,
    };

    const customConfig = service.custom ? service.custom.warmup : undefined;

    return Object.assign(
      this.getGlobalConfig(customConfig, globalDefaultOpts),
      WarmUp.getFunctionConfig(customConfig, functionDefaultOpts),
    );
  }

  /**
   * @description After package initialize hook. Create warmer function and add it to the service.
   *
   * @return {Array} - List of functions to be warmed up and their specific configs
   * */
  static getFunctionsToBeWarmedUp(service, stage, warmupOpts) {
    return service.getAllFunctions()
      .map((name) => service.getFunction(name))
      .map((config) => ({
        name: config.name,
        config: WarmUp.getFunctionConfig(config.warmup, warmupOpts),
      }))
      .filter(({ config: { enabled } }) => (
        enabled === true
        || enabled === 'true'
        || enabled === stage
        || (Array.isArray(enabled) && enabled.indexOf(stage) !== -1)
      ));
  }

  /**
   * @description Clean prefix folder
   *
   * @fulfil {} — Folder cleaned
   * @reject {Error} File system error
   *
   * @return {Promise}
   * */
  async cleanFolder() {
    return fs.remove(this.warmupOpts.pathFolder);
  }

  /**
   * @description Write warm up ES6 function
   *
   * @param {Array} functions - Functions to be warmed up
   *
   * @fulfil {} — Warm up function created
   * @reject {Error} Warm up error
   *
   * @return {Promise}
   * */
  async createWarmUpFunctionArtifact(functions, region, pathFile) {
    /** Log warmup start */
    this.serverless.cli.log(`WarmUp: setting ${functions.length} lambdas to be warm`);

    /** Log functions being warmed up */
    functions.forEach((func) => this.serverless.cli.log(`WarmUp: ${func.name}`));

    const warmUpFunction = `'use strict';

/** Generated by Serverless WarmUp Plugin at ${new Date().toISOString()} */
const aws = require('aws-sdk');
aws.config.region = '${region}';
const lambda = new aws.Lambda();
const functions = ${JSON.stringify(functions)};

module.exports.warmUp = async (event, context) => {
  console.log('Warm Up Start');

  const invokes = await Promise.all(functions.map(async (func) => {
    let concurrency;
    const functionConcurrency = process.env[\`WARMUP_CONCURRENCY_\${func.name.toUpperCase().replace(/-/g, '_')}\`]

    if (functionConcurrency) {
      concurrency = parseInt(functionConcurrency);
      console.log(\`Warming up function: \${func.name} with concurrency: \${concurrency} (from function-specific environment variable)\`);
    } else if (process.env.WARMUP_CONCURRENCY) {
      concurrency = parseInt(process.env.WARMUP_CONCURRENCY);
      console.log(\`Warming up function: \${func.name} with concurrency: \${concurrency} (from global environment variable)\`);
    } else {
      concurrency = parseInt(func.config.concurrency);
      console.log(\`Warming up function: \${func.name} with concurrency: \${concurrency}\`);
    }

    const params = {
      ClientContext: Buffer.from(\`{"custom":\${func.config.payload}}\`).toString('base64'),
      FunctionName: func.name,
      InvocationType: 'RequestResponse',
      LogType: 'None',
      Qualifier: process.env.SERVERLESS_ALIAS || '$LATEST',
      Payload: func.config.payload
    };

    try {
      await Promise.all(Array(concurrency).fill(0).map(async () => await lambda.invoke(params).promise()));
      console.log(\`Warm Up Invoke Success: \${func.name}\`);
      return true;
    } catch (e) {
      console.log(\`Warm Up Invoke Error: \${func.name}\`, e);
      return false;
    }
  }));

  console.log(\`Warm Up Finished with \${invokes.filter(r => !r).length} invoke errors\`);
}`;

    /** Write warm up file */
    return fs.outputFile(pathFile, warmUpFunction);
  }

  /**
   * @description Add warm up function to service
   * */
  static addWarmUpFunctionToService(service, warmupOpts) {
    /** SLS warm up function */
    // eslint-disable-next-line no-param-reassign
    service.functions.warmUpPlugin = {
      description: 'Serverless WarmUp Plugin',
      events: warmupOpts.events,
      handler: warmupOpts.pathHandler,
      memorySize: warmupOpts.memorySize,
      name: warmupOpts.name,
      runtime: 'nodejs12.x',
      package: warmupOpts.package,
      timeout: warmupOpts.timeout,
      ...(Object.keys(warmupOpts.environment).length
        ? { environment: warmupOpts.environment }
        : {}),
      ...(warmupOpts.role ? { role: warmupOpts.role } : {}),
      ...(warmupOpts.tags ? { tags: warmupOpts.tags } : {}),
      ...(warmupOpts.vpc ? { vpc: warmupOpts.vpc } : {}),
    };
  }

  /**
   * @description Warm up the functions immediately after deployment
   *
   * @fulfil {} — Functions warmed up successfully
   * @reject {Error} Functions couldn't be warmed up
   *
   * @return {Promise}
   * */
  async warmUpFunctions(service, warmupOpts) {
    this.serverless.cli.log('WarmUp: Pre-warming up your functions');

    try {
      const { SERVERLESS_ALIAS } = service.getFunction('warmUpPlugin').environment || {};
      const params = {
        FunctionName: warmupOpts.name,
        InvocationType: 'RequestResponse',
        LogType: 'None',
        Qualifier: SERVERLESS_ALIAS || '$LATEST',
        Payload: warmupOpts.payload,
      };

      await this.provider.request('Lambda', 'invoke', params);
      this.serverless.cli.log('WarmUp: Functions successfully pre-warmed');
    } catch (err) {
      this.serverless.cli.log('WarmUp: Error while pre-warming functions', err);
    }
  }
}

/** Export WarmUp class */
module.exports = WarmUp;
<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');
var Config = require('./config');
var Client = require('./client');
var Job = require('./job');

/**
 * @param {Object} configData @see Config.
 */
function PulsarApi(configData) {
  var config = new Config(configData);
  this._clientDefault = new Client(config.url, config.authToken);

  this._clientMap = {};
  _.each(config.auxiliary, function(clientConfig, key) {
    return this._clientMap[key] = new Client(clientConfig.url, clientConfig.authToken);
  }.bind(this));
}

PulsarApi.prototype.getClientDefault = function() {
  return this._clientDefault;
};

PulsarApi.prototype.getClient = function(app, env) {
  var name = this._getClientName(app, env);
  if (this._clientMap[name]) {
    return this._clientMap[name];
  } else {
    return this.getClientDefault();
  }
};

PulsarApi.prototype.createJob = function(app, env, task, taskVariables) {
  return new Job(app, env, task, taskVariables);
};

PulsarApi.prototype.runJob = function(job) {
  var client = this.getClient(job.app, job.env);
  client.runJob(job);
};

PulsarApi.prototype.jobs = function(callback) {
  var clientList = _.toArray(this._clientMap);
  clientList.unshift(this._clientDefault);

  var getClientJobs = function(client, callback) {
    return client.jobs(callback);
  };

  return async.map(clientList, getClientJobs, function(results) {
    var concatenator = function(all, items) {
      return all.concat(items);
    };
    var jobs = _.reduce(results, concatenator, []);
    return callback(jobs);
  });
};

PulsarApi.prototype._getClientName = function(app, env) {
  var name = '';
  if (app) {
    name += app;
  }
  if (env) {
    name += '/' + env;
  }
  return name;
};

module.exports = PulsarApi;
<commit_msg>Update docu.<commit_after>var _ = require('underscore');
var async = require('async');
var Config = require('./config');
var Client = require('./client');
var Job = require('./job');

/**
 * @param {Object} configData @see Config.
 */
function PulsarApi(configData) {
  var config = new Config(configData);
  this._clientDefault = new Client(config.url, config.authToken);

  this._clientMap = {};
  _.each(config.auxiliary, function(clientConfig, key) {
    return this._clientMap[key] = new Client(clientConfig.url, clientConfig.authToken);
  }.bind(this));
}

/**
 * @returns {Client}
 */
PulsarApi.prototype.getClientDefault = function() {
  return this._clientDefault;
};

/**
 * @param {String} app
 * @param {String} env
 * @returns {Client}
 */
PulsarApi.prototype.getClient = function(app, env) {
  var name = this._getClientName(app, env);
  if (this._clientMap[name]) {
    return this._clientMap[name];
  } else {
    return this.getClientDefault();
  }
};

/**
 * @param {String} app
 * @param {String} env
 * @param {String} task
 * @param {Object} taskVariables
 * @returns {Job}
 */
PulsarApi.prototype.createJob = function(app, env, task, taskVariables) {
  return new Job(app, env, task, taskVariables);
};

/**
 * @param {Job} job
 */
PulsarApi.prototype.runJob = function(job) {
  var client = this.getClient(job.app, job.env);
  client.runJob(job);
};

/**
 * @callback PulsarApi~jobsCallback
 * @param {PulsarJob[]} jobs
 */
/**
 * @param {PulsarApi~jobsCallback} callback
 */
PulsarApi.prototype.jobs = function(callback) {
  var clientList = _.toArray(this._clientMap);
  clientList.unshift(this._clientDefault);

  var getClientJobs = function(client, callback) {
    return client.jobs(callback);
  };

  return async.map(clientList, getClientJobs, function(results) {
    var concatenator = function(all, items) {
      return all.concat(items);
    };
    var jobs = _.reduce(results, concatenator, []);
    return callback(jobs);
  });
};

/**
 * @param {String} app
 * @param {String} env
 * @returns {string}
 * @private
 */
PulsarApi.prototype._getClientName = function(app, env) {
  var name = '';
  if (app) {
    name += app;
  }
  if (env) {
    name += '/' + env;
  }
  return name;
};

module.exports = PulsarApi;
<|endoftext|>


<commit_before>exports.wait = require('./wait')
exports.reflow = require('./reflow')

exports.Animation = require('./animation')
exports.Area = require('./area')
exports.Being = require('./being')
exports.Body = require('./body')
exports.DirStateImageMap = require('./dir-state-image-map')
exports.DIRS = require('./const/dirs')
exports.Grid = require('./grid')
exports.GridWalker = require('./grid-walker')
exports.Image = require('./image')
exports.Interval = require('./interval')
exports.LayoutFactory = require('./layout-factory')
exports.Point = require('./point')
exports.Posture = require('./posture')
exports.Prebody = require('./prebody')
exports.Rect = require('./rect')

const decorators = require('./decorators')
exports.decorators = decorators
Object.keys(decorators).forEach(key => { exports[key] = exports.decorators[key] })
<commit_msg>:hammer: refactor(export): export 1 by 1<commit_after>exports.wait = require('./wait')
exports.reflow = require('./reflow')

exports.Animation = require('./animation')
exports.Area = require('./area')
exports.Being = require('./being')
exports.Body = require('./body')
exports.DirStateImageMap = require('./dir-state-image-map')
exports.DIRS = require('./const/dirs')
exports.Grid = require('./grid')
exports.GridWalker = require('./grid-walker')
exports.Image = require('./image')
exports.Interval = require('./interval')
exports.LayoutFactory = require('./layout-factory')
exports.Point = require('./point')
exports.Posture = require('./posture')
exports.Prebody = require('./prebody')
exports.Rect = require('./rect')

const decorators = require('./decorators')
exports.animation = decorators.animation
exports.height = decorators.animation
exports.width = decorators.width
exports.margin = decorators.margin
exports.ratio = decorators.ratio
exports.transition = decorators.transition
<|endoftext|>


<commit_before>import element from 'virtex-element'
import ace from 'brace'

let editor

const defaultProps = {
  name: 'brace-editor',
  mode: 'javascript',
  theme: 'monokai',
  height: '500px',
  width: '500px',
  value: '',
  fontSize: 12,
  showGutter: true,
  onChange: null,
  onPaste: null,
  onLoad: null,
  maxLines: null,
  readOnly: false,
  highlightActiveLine: true,
  showPrintMargin: true,
  tabSize: 2,
  cursorStart: 1,
  editorProps: {},
  wrapEnabled: false
}

function initEditor (props) {
  const {
      name,
      onBeforeLoad,
      mode,
      theme,
      fontSize,
      value,
      cursorStart,
      showGutter,
      wrapEnabled,
      maxLines,
      readOnly,
      highlightActiveLine,
      tabSize,
      showPrintMargin,
      keyboardHandler,
      onLoad
  } = props

  let element = document.getElementById(name)
  editor = ace.edit(name)
  editor.getSession().setMode(`ace/mode/${mode}`)
  editor.setTheme(`ace/theme/${theme}`)
  editor.setFontSize(fontSize)
  editor.setValue(value, cursorStart)
  editor.renderer.setShowGutter(showGutter)
  editor.getSession().setUseWrapMode(wrapEnabled)
  editor.setOption('maxLines', maxLines)
  editor.setOption('readOnly', readOnly)
  editor.setOption('highlightActiveLine', highlightActiveLine)
  editor.setOption('tabSize', tabSize)
  editor.setShowPrintMargin(showPrintMargin)
  editor.on('change', () => element.click())
  editor.on('focus', () => element.focus())
  editor.on('blur', () => element.blur())
  editor.on('copy', text => {
    let evt = new Event('copy', {'bubbles': true, 'cancelable': false})
    return element.dispatchEvent(evt, text)
  })
  editor.on('paste', () => {
    let evt = new Event('paste', {'bubbles': true, 'cancelable': false})
    return element.dispatchEvent(evt)
  })
}

function onCreate ({props, local}) {
  props = {...defaultProps, ...props}
  setTimeout(initEditor.bind(null, props))
}

function render ({props, state, local}) {
  props = {...defaultProps, ...props}
  const {activeLine} = props

  if (editor) {
    editor.getSession().highlightLines(activeLine)
  }

  var divStyle = {
    width: props.width,
    height: props.height
  }
  var className = props.className
  return (
    <div
      id={props.name}
      className={className}
      style={divStyle}
      onFocus={onFocus}
      onClick={onChange}
      onCopy={onCopy}
      onBlur={onBlur}
      onPaste={onPaste} />
  )

  function onFocus () {
    if (props.onFocus) {
      return props.onFocus()
    }
  }

  function onBlur () {
    if (props.onBlur) {
      return props.onBlur()
    }
  }

  // this.silent
  function onChange () {
    if (props.onChange) {
      var value = editor.getValue()
      return props.onChange(value)
    }
  }

  function onCopy (text) {
    if (props.onCopy) {
      return props.onCopy(text)
    }
  }

  function onPaste (text) {
    if (props.onPaste) {
      props.onPaste(text)
    }
  }
}

export default {
  render,
  onCreate
}
<commit_msg>changes<commit_after>import element from 'virtex-element'
import ace from 'brace'

let editor
let lastNum

const defaultProps = {
  name: 'brace-editor',
  mode: 'javascript',
  theme: 'monokai',
  height: '500px',
  width: '500px',
  value: '',
  fontSize: 12,
  showGutter: true,
  onChange: null,
  onPaste: null,
  onLoad: null,
  maxLines: null,
  readOnly: false,
  highlightActiveLine: true,
  showPrintMargin: true,
  tabSize: 2,
  cursorStart: 1,
  editorProps: {},
  wrapEnabled: false
}

function initEditor (props) {
  const {
      name,
      onBeforeLoad,
      mode,
      theme,
      fontSize,
      value,
      cursorStart,
      showGutter,
      wrapEnabled,
      maxLines,
      readOnly,
      highlightActiveLine,
      tabSize,
      showPrintMargin,
      keyboardHandler,
      onLoad
  } = props

  let element = document.getElementById(name)
  editor = ace.edit(name)
  editor.getSession().setMode(`ace/mode/${mode}`)
  editor.setTheme(`ace/theme/${theme}`)
  editor.setFontSize(fontSize)
  editor.setValue(value, cursorStart)
  editor.renderer.setShowGutter(showGutter)
  editor.getSession().setUseWrapMode(wrapEnabled)
  editor.setOption('maxLines', maxLines)
  editor.setOption('readOnly', readOnly)
  editor.setOption('highlightActiveLine', highlightActiveLine)
  editor.setOption('tabSize', tabSize)
  editor.setShowPrintMargin(showPrintMargin)
  editor.on('change', () => element.click())
  editor.on('focus', () => element.focus())
  editor.on('blur', () => element.blur())
  editor.on('copy', text => {
    let evt = new Event('copy', {'bubbles': true, 'cancelable': false})
    return element.dispatchEvent(evt, text)
  })
  editor.on('paste', () => {
    let evt = new Event('paste', {'bubbles': true, 'cancelable': false})
    return element.dispatchEvent(evt)
  })
}

function onCreate ({props, local}) {
  props = {...defaultProps, ...props}
  setTimeout(initEditor.bind(null, props))
}

function trace (lineNum) {
  if (lastNum) {
    editor.getSession().removeMarker(lastNum);
  }
  if (lineNum) {
    lastNum = vm.session.highlightLines(lineNum - 1);
  } else {
    lastNum = null;
  }
}

function render ({props, state, local}) {
  props = {...defaultProps, ...props}
  const {activeLine} = props

  if (editor) {
    trace(activeLine)
  }

  var divStyle = {
    width: props.width,
    height: props.height
  }
  var className = props.className
  return (
    <div
      id={props.name}
      className={className}
      style={divStyle}
      onFocus={onFocus}
      onClick={onChange}
      onCopy={onCopy}
      onBlur={onBlur}
      onPaste={onPaste} />
  )

  function onFocus () {
    if (props.onFocus) {
      return props.onFocus()
    }
  }

  function onBlur () {
    if (props.onBlur) {
      return props.onBlur()
    }
  }

  // this.silent
  function onChange () {
    if (props.onChange) {
      var value = editor.getValue()
      return props.onChange(value)
    }
  }

  function onCopy (text) {
    if (props.onCopy) {
      return props.onCopy(text)
    }
  }

  function onPaste (text) {
    if (props.onPaste) {
      props.onPaste(text)
    }
  }
}

export default {
  render,
  onCreate
}
<|endoftext|>


<commit_before>import Chartkick from 'chartkick'

let chartId = 1

let createComponent = function(Vue, tagName, chartType) {
  let chartProps = [
    "colors", "curve", "decimal", "discrete", "donut", "download", "label",
    "legend", "library", "max", "messages", "min", "points", "prefix", "refresh",
    "stacked", "suffix", "thousands", "title", "xtitle", "xtype", "ytitle"
  ]
  Vue.component(tagName, {
    props: ["data", "id", "width", "height"].concat(chartProps),
    render: function(createElement) {
      return createElement(
        "div",
        {
          attrs: {
            id: this.chartId
          },
          style: this.chartStyle
        },
        ["Loading..."]
      )
    },
    data: function() {
      return {
        chartId: null
      }
    },
    computed: {
      chartStyle: function() {
        // hack to watch data and options
        this.data
        this.chartOptions

        return {
          height: this.height || "300px",
          lineHeight: this.height || "300px",
          width: this.width || "100%",
          textAlign: "center",
          color: "#999",
          fontSize: "14px",
          fontFamily: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif"
        }
      },
      chartOptions: function() {
        let options = {}
        let props = chartProps
        for (let i = 0; i < props.length; i++) {
          let prop = props[i]
          if (this[prop] !== undefined) {
            options[prop] = this[prop]
          }
        }
        return options
      }
    },
    created: function() {
      this.chartId = this.chartId || this.id || ("chart-" + chartId++)
    },
    mounted: function() {
      this.chart = new chartType(this.chartId, this.data, this.chartOptions)
    },
    updated: function() {
      this.chart.updateData(this.data, this.chartOptions)
    }
  })
}

const VueChartkick = {
  version: "0.3.1",
  install: function(Vue, options) {
    if (options && options.adapter) {
      Chartkick.addAdapter(options.adapter)
    }
    createComponent(Vue, "line-chart", Chartkick.LineChart)
    createComponent(Vue, "pie-chart", Chartkick.PieChart)
    createComponent(Vue, "column-chart", Chartkick.ColumnChart)
    createComponent(Vue, "bar-chart", Chartkick.BarChart)
    createComponent(Vue, "area-chart", Chartkick.AreaChart)
    createComponent(Vue, "scatter-chart", Chartkick.ScatterChart)
    createComponent(Vue, "geo-chart", Chartkick.GeoChart)
    createComponent(Vue, "timeline", Chartkick.Timeline)
  },
  addAdapter: function(library) {
    Chartkick.addAdapter(library)
  }
}

// in browser
if (typeof window !== "undefined" && window.Vue) {
  window.Vue.use(VueChartkick)
}

export default VueChartkick
<commit_msg>Destroy chart on destroy<commit_after>import Chartkick from 'chartkick'

let chartId = 1

let createComponent = function(Vue, tagName, chartType) {
  let chartProps = [
    "colors", "curve", "decimal", "discrete", "donut", "download", "label",
    "legend", "library", "max", "messages", "min", "points", "prefix", "refresh",
    "stacked", "suffix", "thousands", "title", "xtitle", "xtype", "ytitle"
  ]
  Vue.component(tagName, {
    props: ["data", "id", "width", "height"].concat(chartProps),
    render: function(createElement) {
      return createElement(
        "div",
        {
          attrs: {
            id: this.chartId
          },
          style: this.chartStyle
        },
        ["Loading..."]
      )
    },
    data: function() {
      return {
        chartId: null
      }
    },
    computed: {
      chartStyle: function() {
        // hack to watch data and options
        this.data
        this.chartOptions

        return {
          height: this.height || "300px",
          lineHeight: this.height || "300px",
          width: this.width || "100%",
          textAlign: "center",
          color: "#999",
          fontSize: "14px",
          fontFamily: "'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif"
        }
      },
      chartOptions: function() {
        let options = {}
        let props = chartProps
        for (let i = 0; i < props.length; i++) {
          let prop = props[i]
          if (this[prop] !== undefined) {
            options[prop] = this[prop]
          }
        }
        return options
      }
    },
    created: function() {
      this.chartId = this.chartId || this.id || ("chart-" + chartId++)
    },
    mounted: function() {
      this.chart = new chartType(this.chartId, this.data, this.chartOptions)
    },
    updated: function() {
      this.chart.updateData(this.data, this.chartOptions)
    },
    beforeDestroy: function() {
      this.chart.destroy()
    }
  })
}

const VueChartkick = {
  version: "0.3.1",
  install: function(Vue, options) {
    if (options && options.adapter) {
      Chartkick.addAdapter(options.adapter)
    }
    createComponent(Vue, "line-chart", Chartkick.LineChart)
    createComponent(Vue, "pie-chart", Chartkick.PieChart)
    createComponent(Vue, "column-chart", Chartkick.ColumnChart)
    createComponent(Vue, "bar-chart", Chartkick.BarChart)
    createComponent(Vue, "area-chart", Chartkick.AreaChart)
    createComponent(Vue, "scatter-chart", Chartkick.ScatterChart)
    createComponent(Vue, "geo-chart", Chartkick.GeoChart)
    createComponent(Vue, "timeline", Chartkick.Timeline)
  },
  addAdapter: function(library) {
    Chartkick.addAdapter(library)
  }
}

// in browser
if (typeof window !== "undefined" && window.Vue) {
  window.Vue.use(VueChartkick)
}

export default VueChartkick
<|endoftext|>


<commit_before>export * as actionTypes from './actions'

export default function main (options) {
  if (!window.analytics) {
    throw new Error('Segment.io analytics.js library is not loaded')
  }

  return middleware(options)
}

const middleware = options => next => action => {
  if (!action.meta || !action.meta.analytics) {
    return next(action)
  }

  const { name, type, payload } = action.meta.analytics

  if (!type) {
    throw new Error('Action type is not set...')
  }

  window.analytics[type](name || action.type, payload)

  return next(action)
}
<commit_msg>added normalizer option to normalize data from i.e Immutable.js<commit_after>export * as actionTypes from './actions'

export default function main (options) {
  if (!window.analytics) {
    throw new Error('Segment.io analytics.js library is not loaded')
  }

  return middleware(options)
}

const middleware = options => store => next => action => {
  if (!action.meta || !action.meta.analytics) {
    return next(action)
  }

  const { name, type, payload } = action.meta.analytics

  if (!type) {
    throw new Error('Action type is not set...')
  }

  window.analytics[type](name || action.type, options.normalizer
    ? options.normalizer(payload)
    : payload)

  return next(action)
}
<|endoftext|>


<commit_before>'use strict';

import jsondiffpatch from 'jsondiffpatch';

const diffpatch = jsondiffpatch.create({ objectHash: (obj) => obj.id });

/**
 * Calculates the differences between two customer objects and builds the update
 * actions.
 *
 * @public
 * @param {Object} before Original customer
 * @param {Object} after Updated customer
 * @return {Array} Update actions
 */
function buildActions(before, after) {
  const changes = diffpatch.diff(before, after) || {};
  const nameFields = [
    'middleName',
    'firstName',
    'lastName',
    'title'
  ];
  const actions = [];

  Object.keys(changes).forEach((key) => {
    const change = changes[key];

    if (~nameFields.indexOf(key)) {
      //
      // Here we assume that the new object is validated, so if there is a
      // difference in the `firstName` or `lastName` field, this difference
      // must consist in a different non empty string.
      //
      let action = actions.find((action) => {
        return action.action === 'changeName' ? true : false;
      });

      //
      // Create and append the action if we can't find one.
      //
      if (!action) {
        action = {
          firstName: before.firstName,
          lastName: before.lastName,
          action: 'changeName'
        };
        actions.push(action);
      }

      if (change.length === 1) {
        action[key] = change[0];
      } else if (change.length === 2) {
        action[key] = change[1];
      }
    } else if (key === 'email') {
      actions.push({ action: 'changeEmail', email: change[1] });
    } else if (key === 'addresses') {
      Object.keys(change).forEach((key) => {
        //
        // This property has no special meaning for us.
        //
        if (key === '_t') return;

        const delta = change[key];

        //
        // The address has been moved or removed.
        //
        if (key.charAt(0) === '_') {
          if (!delta[2]) {
            actions.push({ action: 'removeAddress', addressId: delta[0].id });
          }
          return;
        }

        //
        // The address has been changed or inserted.
        //
        if (Array.isArray(delta)) {
          actions.push({ action: 'addAddress', address: delta[0] });
        } else {
          actions.push({
            addressId: after.addresses[key].id,
            address: after.addresses[key],
            action: 'changeAddress'
          });
        }
      });
    }
  });

  return actions;
}

//
// Expose the `buildActions` function.
//
export { buildActions as default };
<commit_msg>Save a reference to the `changeName` action instead of looping the array<commit_after>'use strict';

import jsondiffpatch from 'jsondiffpatch';

const diffpatch = jsondiffpatch.create({ objectHash: (obj) => obj.id });
const nameFields = [
  'middleName',
  'firstName',
  'lastName',
  'title'
];

/**
 * Calculates the differences between two customer objects and builds the update
 * actions.
 *
 * @public
 * @param {Object} before Original customer
 * @param {Object} after Updated customer
 * @return {Array} Update actions
 */
function buildActions(before, after) {
  const changes = diffpatch.diff(before, after) || {};
  const actions = [];
  let changeName;

  Object.keys(changes).forEach((key) => {
    const change = changes[key];

    if (~nameFields.indexOf(key)) {
      //
      // Create and append the action if we don't have one (the `firstName`
      // and `lastName` fields can not be removed).
      //
      if (!changeName) {
        changeName = {
          firstName: before.firstName,
          lastName: before.lastName,
          action: 'changeName'
        };
        actions.push(changeName);
      }

      if (change.length === 1) {
        changeName[key] = change[0];
      } else if (change.length === 2) {
        changeName[key] = change[1];
      }
    } else if (key === 'email') {
      actions.push({ action: 'changeEmail', email: change[1] });
    } else if (key === 'addresses') {
      Object.keys(change).forEach((key) => {
        //
        // This property has no special meaning for us.
        //
        if (key === '_t') return;

        const delta = change[key];

        //
        // The address has been moved or removed.
        //
        if (key.charAt(0) === '_') {
          if (!delta[2]) {
            actions.push({ action: 'removeAddress', addressId: delta[0].id });
          }
          return;
        }

        //
        // The address has been changed or inserted.
        //
        if (Array.isArray(delta)) {
          actions.push({ action: 'addAddress', address: delta[0] });
        } else {
          actions.push({
            addressId: after.addresses[key].id,
            address: after.addresses[key],
            action: 'changeAddress'
          });
        }
      });
    }
  });

  return actions;
}

//
// Expose the `buildActions` function.
//
export { buildActions as default };
<|endoftext|>


<commit_before>/* eslint no-underscore-dangle: 0 */

import fs from 'fs';
import mkdirp from 'mkdirp';
import path from 'path';
import rimraf from 'rimraf';
import {
  isFunction,
  tryParseJson,
  tryStringifyJson,
  processPath,
  processPathNoJson,
} from './utils';

/**
 * _get - function the gets filePath and a callback and returns a parse json
 *        from the file in the specefied path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {function} cb - a callback function
 */
function _get(filePath, cb) {
  const fullPath = processPath(filePath);
  return fs.readFile(fullPath, { encoding: 'utf8' }, (err, json) => {
    if (!err) {
      const object = tryParseJson(json);

      if (object instanceof Error) {
        return cb(new Error(`The file in path ${fullPath} is not a valid json file`), null);
      }

      return cb(null, object);
    }

    if (err.code === 'ENOENT') {
      return cb(new Error(`The file in path ${fullPath} doesn\'t exist`), null);
    }

    return cb(err);
  });
}

/**
 * get - function the gets filePath and a callback and returns a parse json
 *       from the file in the specefied path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {undefined | function} cb - an optional callback function
 * @return {undefined | Promise} if there is only the first argument, the function
 *                               will return a thenable Promise object
 */
function get(filePath, cb) {
  if (cb && isFunction(cb)) {
    return _get(filePath, cb);
  }

  return new Promise((resolve, reject) =>
    _get(filePath, (err, data) => {
      if (err) return reject(err);
      return resolve(data);
    })
  );
}

/**
 * _set - sets a json file into the storage at a path (relative to the `userData` folder)
 *        also stringify the json if needed and create any folder that is required in the path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {string | object} data - the data to save in the file path, can be parseJson or an object
 * @param  {type} cb - a callback function
 */
function _set(filePath, data, cb) {
  const fullPath = processPath(filePath);
  const json = tryStringifyJson(data);

  if (json instanceof Error) {
    return cb(new Error(`The file you trying to save at path ${fullPath} is not valid json`));
  }

  const dir = path.dirname(fullPath);

  return fs.access(dir, fs.F_OK, (notExists) => {
    if (!notExists) return fs.writeFile(fullPath, json, cb);
    return mkdirp(dir, (err) => {
      if (err) return cb(err);
      return fs.writeFile(fullPath, json, cb);
    });
  });
}

/**
 * set - sets a json file into the storage at a path (relative to the `userData` folder)
 *       also stringify the json if needed and create any folder that is required in the path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {string | object} data - the data to save in the file path, can be parseJson or an object
 * @param  {undefined | function} cb - an optional callback function
 * @return {undefined | Promise} if there are only two first arguments, the function
 *                               will return a thenable Promise object
 */

function set(filePath, data, cb) {
  if (cb && isFunction(cb)) {
    return _set(filePath, data, cb);
  }

  return new Promise((resolve, reject) =>
    _set(filePath, data, (err) => {
      if (err) return reject(err);
      return resolve();
    })
  );
}

/**
 * _isPathExists - check whether the path inserted is exist in the userData directory
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {func} cb - a callback function
 */
function _isPathExists(fileOrDirPath, cb) {
  const fullPath = processPathNoJson(fileOrDirPath);

  return fs.exists(fullPath, (exists) => {
    if (exists) return cb(true);
    return cb(false);
  });
}

/**
 * isPathExists - check whether the path inserted is exist in the userData directory
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {undefined|func} cb - an optional callback function
 * @return {undefined | Promise} if there are only two first arguments, the function
 *                               will return a thenable Promise object
 */
function isPathExists(fileOrDirPath, cb) {
  if (cb && isFunction(cb)) {
    return _isPathExists(fileOrDirPath, cb);
  }

  return new Promise(resolve =>
    _isPathExists(fileOrDirPath, (result) =>
      resolve(result)
    )
  );
}

/**
 * _remove - remove the file/folder from the path inserted
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {func} cb - a callback function
 */
function _remove(fileOrDirPath, cb) {
  const fullPath = processPathNoJson(fileOrDirPath);

  return rimraf(fullPath, cb);
}

/**
 * remove - remove the file/folder from the path inserted
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {undefined|func} cb - an optional callback function
 * @return {undefined | Promise} if there are only two first arguments, the function
 *                               will return a thenable Promise object
 */
function remove(fileOrDirPath, cb) {
  if (cb && isFunction(cb)) {
    return _remove(fileOrDirPath, cb);
  }

  return new Promise((resolve, reject) =>
    _remove(fileOrDirPath, error => {
      if (error) return reject(error);
      return resolve();
    })
  );
}

module.exports = {
  get,
  set,
  isPathExists,
  remove,
};
<commit_msg>Add human readable message to existing ENOENT error<commit_after>/* eslint no-underscore-dangle: 0 */

import fs from 'fs';
import mkdirp from 'mkdirp';
import path from 'path';
import rimraf from 'rimraf';
import {
  isFunction,
  tryParseJson,
  tryStringifyJson,
  processPath,
  processPathNoJson,
} from './utils';

/**
 * _get - function the gets filePath and a callback and returns a parse json
 *        from the file in the specefied path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {function} cb - a callback function
 */
function _get(filePath, cb) {
  const fullPath = processPath(filePath);
  return fs.readFile(fullPath, { encoding: 'utf8' }, (err, json) => {
    if (!err) {
      const object = tryParseJson(json);

      if (object instanceof Error) {
        return cb(new Error(`The file in path ${fullPath} is not a valid json file`), null);
      }

      return cb(null, object);
    }

    if (err.code === 'ENOENT') {
      err.message = `The file in path ${fullPath} doesn\'t exist`;
    }

    return cb(err);
  });
}

/**
 * get - function the gets filePath and a callback and returns a parse json
 *       from the file in the specefied path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {undefined | function} cb - an optional callback function
 * @return {undefined | Promise} if there is only the first argument, the function
 *                               will return a thenable Promise object
 */
function get(filePath, cb) {
  if (cb && isFunction(cb)) {
    return _get(filePath, cb);
  }

  return new Promise((resolve, reject) =>
    _get(filePath, (err, data) => {
      if (err) return reject(err);
      return resolve(data);
    })
  );
}

/**
 * _set - sets a json file into the storage at a path (relative to the `userData` folder)
 *        also stringify the json if needed and create any folder that is required in the path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {string | object} data - the data to save in the file path, can be parseJson or an object
 * @param  {type} cb - a callback function
 */
function _set(filePath, data, cb) {
  const fullPath = processPath(filePath);
  const json = tryStringifyJson(data);

  if (json instanceof Error) {
    return cb(new Error(`The file you trying to save at path ${fullPath} is not valid json`));
  }

  const dir = path.dirname(fullPath);

  return fs.access(dir, fs.F_OK, (notExists) => {
    if (!notExists) return fs.writeFile(fullPath, json, cb);
    return mkdirp(dir, (err) => {
      if (err) return cb(err);
      return fs.writeFile(fullPath, json, cb);
    });
  });
}

/**
 * set - sets a json file into the storage at a path (relative to the `userData` folder)
 *       also stringify the json if needed and create any folder that is required in the path
 *
 * @param  {string} filePath - path to the file relative to the `userData` folder
 * @param  {string | object} data - the data to save in the file path, can be parseJson or an object
 * @param  {undefined | function} cb - an optional callback function
 * @return {undefined | Promise} if there are only two first arguments, the function
 *                               will return a thenable Promise object
 */

function set(filePath, data, cb) {
  if (cb && isFunction(cb)) {
    return _set(filePath, data, cb);
  }

  return new Promise((resolve, reject) =>
    _set(filePath, data, (err) => {
      if (err) return reject(err);
      return resolve();
    })
  );
}

/**
 * _isPathExists - check whether the path inserted is exist in the userData directory
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {func} cb - a callback function
 */
function _isPathExists(fileOrDirPath, cb) {
  const fullPath = processPathNoJson(fileOrDirPath);

  return fs.exists(fullPath, (exists) => {
    if (exists) return cb(true);
    return cb(false);
  });
}

/**
 * isPathExists - check whether the path inserted is exist in the userData directory
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {undefined|func} cb - an optional callback function
 * @return {undefined | Promise} if there are only two first arguments, the function
 *                               will return a thenable Promise object
 */
function isPathExists(fileOrDirPath, cb) {
  if (cb && isFunction(cb)) {
    return _isPathExists(fileOrDirPath, cb);
  }

  return new Promise(resolve =>
    _isPathExists(fileOrDirPath, (result) =>
      resolve(result)
    )
  );
}

/**
 * _remove - remove the file/folder from the path inserted
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {func} cb - a callback function
 */
function _remove(fileOrDirPath, cb) {
  const fullPath = processPathNoJson(fileOrDirPath);

  return rimraf(fullPath, cb);
}

/**
 * remove - remove the file/folder from the path inserted
 *
 * @param  {string} fileOrDirPath - a path inside of the userData directory
 * @param  {undefined|func} cb - an optional callback function
 * @return {undefined | Promise} if there are only two first arguments, the function
 *                               will return a thenable Promise object
 */
function remove(fileOrDirPath, cb) {
  if (cb && isFunction(cb)) {
    return _remove(fileOrDirPath, cb);
  }

  return new Promise((resolve, reject) =>
    _remove(fileOrDirPath, error => {
      if (error) return reject(error);
      return resolve();
    })
  );
}

module.exports = {
  get,
  set,
  isPathExists,
  remove,
};
<|endoftext|>


<commit_before>function numberToText(num, language)
{
  var lang = new Array("indian", "english"); //make in lower case

  if(isNaN(num))
     return "Invalid number.";

  if(!isInt(num))
    return "Currently, currency/decimal support is unavailable.";

    if(num < 0)
        return "Please enter +ve number only.";

  /* To disallow large numbers -uncomment
  if(!isInRange(num))
    return "Please enter number between 0 - 999999999.";
*/
    if(isBlank(language))
        language = "indian";

   if(lang.indexOf(language.toLowerCase()) == -1)
        return "Support for language: " + language + " is not available. Available languages are: " + lang.toString();

  return toText(num,language); //currently supports for Indian number conversions
}

function isInt(num)   {return (num === parseInt(num,10));}

function isInRange(num)  {return !((num < 0) || (num > 999999999));}

function isBlank(str) {    return (!str || /^\s*$/.test(str));}

function toTitleCase(str)
{
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

function toText(num,type){
    var res;

    switch (type.toLowerCase()) {
        case "indian":
            res = toIndianText(num);
            break;
        case "english":
            res = toEnglishText(num);
            break;
    }
    return res;
}

function toEnglishText(num)
{
    //For English conversion

    var quintillion = Math.floor(num / 1000000000000000000); /* quintillion */
    num -= quintillion * 1000000000000000000;
    var quar = Math.floor(num / 1000000000000000); /* quadrillion */
    num -= quar * 1000000000000000;
    var trin = Math.floor(num / 1000000000000); /* trillion */
    num -= trin * 1000000000000;
    var Gn = Math.floor(num / 1000000000); /* billion */
    num -= Gn * 1000000000;
    var million = Math.floor(num / 1000000); /* million */
    num -= million * 1000000;
    var Hn = Math.floor(num / 1000); /* thousand */
    num -= Hn * 1000;
    var Dn = Math.floor(num / 100); /* Tens (deca) */
    num = num % 100; /* Ones */
    var tn = Math.floor(num / 10);
    var one = Math.floor(num % 10);
    var res = "";

    if (quintillion > 0) {
        res += (toEnglishText(quintillion) + " Quintillion");
    }
    if (quar > 0) {
        res += (toEnglishText(quar) + " Quadrillion");
    }
    if (trin > 0) {
        res += (toEnglishText(trin) + " Trillion");
    }
    if (Gn > 0) {
        res += (toEnglishText(Gn) + " Billion");
    }
    if (million > 0) {
        res += (((res == "") ? "" : " ") + toEnglishText(million) + " Million");
    }
    if (Hn > 0) {
        res += (((res == "") ? "" : " ") + toEnglishText(Hn) + " Thousand");
    }

    if (Dn) {
        res += (((res == "") ? "" : " ") + toEnglishText(Dn) + " Hundred");
    }

    var ones = Array("", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eightteen", "Nineteen");
    var tens = Array("", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety");

    if (tn > 0 || one > 0) {
        if(isCurrency())
        {
            if (!(res == "")) {
            res += " And "; //for currency only
            }
        }

        if (!(res == "")) {
            res += " ";
        }

        if (tn < 2) {
            res += ones[tn * 10 + one];
        } else {

            res += tens[tn];
            if (one > 0) {
                res += ("-" + ones[one]);
            }
        }
    }

    if (res == "") {
        res = "Zero";
    }
    return res;
}

//This function is used for Indian conversion only
function toIndianText(num){
    var Gn = Math.floor(num / 10000000);  /* Crore */
    num -= Gn * 10000000;
    var kn = Math.floor(num / 100000);     /* lakhs */
    num -= kn * 100000;
    var Hn = Math.floor(num / 1000);      /* thousand */
    num -= Hn * 1000;
    var Dn = Math.floor(num / 100);       /* Tens (deca) */
    num = num % 100;               /* Ones */
    var tn= Math.floor(num / 10);
    var one=Math.floor(num % 10);

    var res = "";

    if (Gn>0)
    {
        res += (toIndianText(Gn) + " Crore");
    }
    if (kn>0)
    {
            res += (((res=="") ? "" : " ") +
            toIndianText(kn) + " Lakh");
    }
    if (Hn>0)
    {
        res += (((res=="") ? "" : " ") +
            toIndianText(Hn) + " Thousand");
    }

    if (Dn)
    {
        res += (((res=="") ? "" : " ") +
            toIndianText(Dn) + " Hundred");
    }

    var ones = Array("", "One", "Two", "Three", "Four", "Five", "Six","Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen","Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen","Nineteen");
    var tens = Array("", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty","Seventy", "Eighty", "Ninety");

    if (tn>0 || one>0)
    {
        if(isCurrency())
        {
            if (!(res==""))
            {
                res += " And ";  //Reserve it only for Currentcy
            }
        }

        if (!(res==""))
            {
                res += " ";
            }

        if (tn < 2)
        {
            res += ones[tn * 10 + one];
        }
        else
        {

            res += tens[tn];
            if (one>0)
            {
                res += ("-" + ones[one]);
            }
        }
    }

    if (res=="")
    {
        res = "Zero";
    }
    return res;

}

function isCurrency()
{
    return false;   //Reserved for future, this function will accept one parameter for currency
}

//export
module.exports = numberToText;
<commit_msg>removed unused code<commit_after>function numberToText(num, language)
{
  var lang = new Array("indian", "english"); //make in lower case

  if(isNaN(num))
     return "Invalid number.";

  if(!isInt(num))
    return "Currently, currency/decimal support is unavailable.";

    if(num < 0)
        return "Please enter +ve number only.";

  /* To disallow large numbers -uncomment
  if(!isInRange(num))
    return "Please enter number between 0 - 999999999.";
*/
    if(isBlank(language))
        language = "indian";

   if(lang.indexOf(language.toLowerCase()) == -1)
        return "Support for language: " + language + " is not available. Available languages are: " + lang.toString();

  return toText(num,language); //currently supports for Indian number conversions
}

function isInt(num)   {return (num === parseInt(num,10));}

function isInRange(num)  {return !((num < 0) || (num > 999999999));}

function isBlank(str) {    return (!str || /^\s*$/.test(str));}

function toText(num,type){
    var res;

    switch (type.toLowerCase()) {
        case "indian":
            res = toIndianText(num);
            break;
        case "english":
            res = toEnglishText(num);
            break;
    }
    return res;
}

function toEnglishText(num)
{
    //For English conversion

    var quintillion = Math.floor(num / 1000000000000000000); /* quintillion */
    num -= quintillion * 1000000000000000000;
    var quar = Math.floor(num / 1000000000000000); /* quadrillion */
    num -= quar * 1000000000000000;
    var trin = Math.floor(num / 1000000000000); /* trillion */
    num -= trin * 1000000000000;
    var Gn = Math.floor(num / 1000000000); /* billion */
    num -= Gn * 1000000000;
    var million = Math.floor(num / 1000000); /* million */
    num -= million * 1000000;
    var Hn = Math.floor(num / 1000); /* thousand */
    num -= Hn * 1000;
    var Dn = Math.floor(num / 100); /* Tens (deca) */
    num = num % 100; /* Ones */
    var tn = Math.floor(num / 10);
    var one = Math.floor(num % 10);
    var res = "";

    if (quintillion > 0) {
        res += (toEnglishText(quintillion) + " Quintillion");
    }
    if (quar > 0) {
        res += (toEnglishText(quar) + " Quadrillion");
    }
    if (trin > 0) {
        res += (toEnglishText(trin) + " Trillion");
    }
    if (Gn > 0) {
        res += (toEnglishText(Gn) + " Billion");
    }
    if (million > 0) {
        res += (((res == "") ? "" : " ") + toEnglishText(million) + " Million");
    }
    if (Hn > 0) {
        res += (((res == "") ? "" : " ") + toEnglishText(Hn) + " Thousand");
    }

    if (Dn) {
        res += (((res == "") ? "" : " ") + toEnglishText(Dn) + " Hundred");
    }

    var ones = Array("", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eightteen", "Nineteen");
    var tens = Array("", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety");

    if (tn > 0 || one > 0) {
        if(isCurrency())
        {
            if (!(res == "")) {
            res += " And "; //for currency only
            }
        }

        if (!(res == "")) {
            res += " ";
        }

        if (tn < 2) {
            res += ones[tn * 10 + one];
        } else {

            res += tens[tn];
            if (one > 0) {
                res += ("-" + ones[one]);
            }
        }
    }

    if (res == "") {
        res = "Zero";
    }
    return res;
}

//This function is used for Indian conversion only
function toIndianText(num){
    var Gn = Math.floor(num / 10000000);  /* Crore */
    num -= Gn * 10000000;
    var kn = Math.floor(num / 100000);     /* lakhs */
    num -= kn * 100000;
    var Hn = Math.floor(num / 1000);      /* thousand */
    num -= Hn * 1000;
    var Dn = Math.floor(num / 100);       /* Tens (deca) */
    num = num % 100;               /* Ones */
    var tn= Math.floor(num / 10);
    var one=Math.floor(num % 10);

    var res = "";

    if (Gn>0)
    {
        res += (toIndianText(Gn) + " Crore");
    }
    if (kn>0)
    {
            res += (((res=="") ? "" : " ") +
            toIndianText(kn) + " Lakh");
    }
    if (Hn>0)
    {
        res += (((res=="") ? "" : " ") +
            toIndianText(Hn) + " Thousand");
    }

    if (Dn)
    {
        res += (((res=="") ? "" : " ") +
            toIndianText(Dn) + " Hundred");
    }

    var ones = Array("", "One", "Two", "Three", "Four", "Five", "Six","Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen","Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen","Nineteen");
    var tens = Array("", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty","Seventy", "Eighty", "Ninety");

    if (tn>0 || one>0)
    {
        if(isCurrency())
        {
            if (!(res==""))
            {
                res += " And ";  //Reserve it only for Currentcy
            }
        }

        if (!(res==""))
            {
                res += " ";
            }

        if (tn < 2)
        {
            res += ones[tn * 10 + one];
        }
        else
        {

            res += tens[tn];
            if (one>0)
            {
                res += ("-" + ones[one]);
            }
        }
    }

    if (res=="")
    {
        res = "Zero";
    }
    return res;

}

function isCurrency()
{
    return false;   //Reserved for future, this function will accept one parameter for currency
}

//export
module.exports = numberToText;
<|endoftext|>


<commit_before>export function onConnect(init, responses, connections, onDisconnect) {
  if (typeof connections === 'undefined' && !window.bgConnections) {
    window.bgConnections = {}; connections = window.bgConnections;
  }

  function onConnectListener(port) {
    function extensionListener(message) {
      if (init && message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;
        port.postMessage(init(message.tabId || port.sender.tab.id));
      }
      else if(responses[message.name]) {
        const res = responses[message.name](message, port);
        if (res) port.postMessage(res);
        else if (window.bgConnections) {
          sendToTabsExcept(message, port, window.bgConnections);
        }
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      if (onDisconnect) onDisconnect(portDiscon);
      Object.keys(connections).some(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
          return true;
        }
        return false;
      });
    });
  }

  chrome.runtime.onConnect.addListener(onConnectListener);
  chrome.runtime.onConnectExternal.addListener(onConnectListener);
}

export function connect(arg) {
  if (!arg) return chrome.runtime.connect();
  if (typeof arg === 'boolean' && arg) {
    window.bgConnection = chrome.runtime.connect();
    return window.bgConnection;
  }
  return chrome.runtime.connect(arg);
}

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
  if (chrome.runtime.onMessageExternal) chrome.runtime.onMessageExternal.addListener(messaging);
}

export function sendToBg(...args) {
  if (!window.bgConnection) chrome.runtime.sendMessage(...args);
  else {
    window.bgConnection.postMessage(...args);
  }
}

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function sendToTabs(message, connections) {
  if (!connections) {
    if (window.bgConnections) connections = window.bgConnections;
    else return;
  }
  Object.keys(connections).forEach(function(id) {
    connections[id].postMessage(message);
  });
}

export function sendToTabsExcept(message, port, connections) {
  Object.keys(connections).forEach(function(id) {
    if (connections[id] !== port) {
      connections[id].postMessage(message);
    }
  });
}

export function sendMessage(message) {
  if (window.bgConnection) window.bgConnection.postMessage(message);
  else sendToTabs(message);
}
<commit_msg>improve browser compatibility when onConnectExternal not supported (#5)<commit_after>export function onConnect(init, responses, connections, onDisconnect) {
  if (typeof connections === 'undefined' && !window.bgConnections) {
    window.bgConnections = {}; connections = window.bgConnections;
  }

  function onConnectListener(port) {
    function extensionListener(message) {
      if (init && message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;
        port.postMessage(init(message.tabId || port.sender.tab.id));
      }
      else if(responses[message.name]) {
        const res = responses[message.name](message, port);
        if (res) port.postMessage(res);
        else if (window.bgConnections) {
          sendToTabsExcept(message, port, window.bgConnections);
        }
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      if (onDisconnect) onDisconnect(portDiscon);
      Object.keys(connections).some(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
          return true;
        }
        return false;
      });
    });
  }

  chrome.runtime.onConnect.addListener(onConnectListener);
  if (chrome.runtime.onConnectExternal) chrome.runtime.onConnectExternal.addListener(onConnectListener);
}

export function connect(arg) {
  if (!arg) return chrome.runtime.connect();
  if (typeof arg === 'boolean' && arg) {
    window.bgConnection = chrome.runtime.connect();
    return window.bgConnection;
  }
  return chrome.runtime.connect(arg);
}

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
  if (chrome.runtime.onMessageExternal) chrome.runtime.onMessageExternal.addListener(messaging);
}

export function sendToBg(...args) {
  if (!window.bgConnection) chrome.runtime.sendMessage(...args);
  else {
    window.bgConnection.postMessage(...args);
  }
}

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function sendToTabs(message, connections) {
  if (!connections) {
    if (window.bgConnections) connections = window.bgConnections;
    else return;
  }
  Object.keys(connections).forEach(function(id) {
    connections[id].postMessage(message);
  });
}

export function sendToTabsExcept(message, port, connections) {
  Object.keys(connections).forEach(function(id) {
    if (connections[id] !== port) {
      connections[id].postMessage(message);
    }
  });
}

export function sendMessage(message) {
  if (window.bgConnection) window.bgConnection.postMessage(message);
  else sendToTabs(message);
}
<|endoftext|>