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

const express = require('express')
const app = express()
const port = 3000

var Client = module.exports = function (config) {
  if (! config) config = {};

  this.version = config.version || '1.0.0';
  this.protocol = 'https';
  this.host = 'api.producthunt.com';
  this.pathPrefix = '/v1';
  this.credentials = {
    client_id: config.client_id,
    client_secret: config.client_secret,
    grant_type: config.grant_type
  };

  if (config.redirect_uri && config.code) {
    this.credentials.redirect_uri = config.redirect_uri;
    this.credentials.code = config.code;
  }

  this.setupAPI();
};

Client.prototype.setupAPI = function () {
  this.posts = require(`./api/v${this.version}/posts`)(this);
  this.users = require(`./api/v${this.version}/users`)(this);
  this.collections = require(`./api/v${this.version}/collections`)(this);
  this.comments = require(`./api/v${this.version}/comments`)(this);
  this.notifications = require(`./api/v${this.version}/notifications`)(this);
  this.votes = require(`./api/v${this.version}/votes`)(this);
  this.settings = require(`./api/v${this.version}/settings`)(this);
  this.relatedLinks = require(`./api/v${this.version}/related_links`)(this);
  this.followers = require(`./api/v${this.version}/followers`)(this);
  this.currentUser = require(`./api/v${this.version}/current_user`)(this);
  this.categories = require(`./api/v${this.version}/categories`)(this);
  this.live = require(`./api/v${this.version}/live`)(this);
  this.topics = require(`./api/v${this.version}/topics`)(this);
};

Client.prototype.getEndpoint = function(path) {
  var base = `${this.protocol}://${this.host}`;
  var route = `${this.pathPrefix}${path}`;

  return `${base}${route}`;
};

Client.prototype.authenticate = function (done) {
  var endpoint = this.getEndpoint('/oauth/token');
  var options = {
    url: endpoint,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'Host': 'api.producthunt.com'
    },
    json: this.credentials
  };

  request.post(options, (err, res, body) => {
    if (err) {
      console.log('Error while authenticating');
      done(err);
    }

    if (res.statusCode === 200) {
      done(null, body.access_token);
    } else {
      //TODO: JSON.stringify?
      var error = res.body;
      done(error);
    }
  });
};

Client.prototype._sendHttpRequest = function (method, path, options, done) {
  var endpoint = this.getEndpoint(path);
  this.authenticate(function (error, access_token) {
    if (error) return done(error);

    var opts = {
      url: endpoint,
      method: method,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${access_token}`,
        'Host': 'api.producthunt.com'
      },
    };

    if (options.params) {
      opts.qs = options.params;
    }

    if (options.body) {
      opts.json = true;
      opts.body = options.body;
    }

    request(opts, (err, res) => {
      if (err) return done(err);

      done(null, res);
    });
  });
};

Client.prototype.httpGet = function (path, params, done) {
  var options = {
    params: params
  };

  this._sendHttpRequest('GET', path, options, done);
};

Client.prototype.httpPost = function (path, options, done) {
  this._sendHttpRequest('POST', path, options, done);
};

Client.prototype.httpPut = function (path, options, done) {
  this._sendHttpRequest('PUT', path, options, done);
};

Client.prototype.httpDelete = function (path, options, done) {
  this._sendHttpRequest('DELETE', path, options, done);
};
<commit_msg>remove express import<commit_after>var request = require('request');

var Client = module.exports = function (config) {
  if (! config) config = {};

  this.version = config.version || '1.0.0';
  this.protocol = 'https';
  this.host = 'api.producthunt.com';
  this.pathPrefix = '/v1';
  this.credentials = {
    client_id: config.client_id,
    client_secret: config.client_secret,
    grant_type: config.grant_type
  };

  if (config.redirect_uri && config.code) {
    this.credentials.redirect_uri = config.redirect_uri;
    this.credentials.code = config.code;
  }

  this.setupAPI();
};

Client.prototype.setupAPI = function () {
  this.posts = require(`./api/v${this.version}/posts`)(this);
  this.users = require(`./api/v${this.version}/users`)(this);
  this.collections = require(`./api/v${this.version}/collections`)(this);
  this.comments = require(`./api/v${this.version}/comments`)(this);
  this.notifications = require(`./api/v${this.version}/notifications`)(this);
  this.votes = require(`./api/v${this.version}/votes`)(this);
  this.settings = require(`./api/v${this.version}/settings`)(this);
  this.relatedLinks = require(`./api/v${this.version}/related_links`)(this);
  this.followers = require(`./api/v${this.version}/followers`)(this);
  this.currentUser = require(`./api/v${this.version}/current_user`)(this);
  this.categories = require(`./api/v${this.version}/categories`)(this);
  this.live = require(`./api/v${this.version}/live`)(this);
  this.topics = require(`./api/v${this.version}/topics`)(this);
};

Client.prototype.getEndpoint = function(path) {
  var base = `${this.protocol}://${this.host}`;
  var route = `${this.pathPrefix}${path}`;

  return `${base}${route}`;
};

Client.prototype.authenticate = function (done) {
  var endpoint = this.getEndpoint('/oauth/token');
  var options = {
    url: endpoint,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'Host': 'api.producthunt.com'
    },
    json: this.credentials
  };

  request.post(options, (err, res, body) => {
    if (err) {
      console.log('Error while authenticating');
      done(err);
    }

    if (res.statusCode === 200) {
      done(null, body.access_token);
    } else {
      //TODO: JSON.stringify?
      var error = res.body;
      done(error);
    }
  });
};

Client.prototype._sendHttpRequest = function (method, path, options, done) {
  var endpoint = this.getEndpoint(path);
  this.authenticate(function (error, access_token) {
    if (error) return done(error);

    var opts = {
      url: endpoint,
      method: method,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${access_token}`,
        'Host': 'api.producthunt.com'
      },
    };

    if (options.params) {
      opts.qs = options.params;
    }

    if (options.body) {
      opts.json = true;
      opts.body = options.body;
    }

    request(opts, (err, res) => {
      if (err) return done(err);

      done(null, res);
    });
  });
};

Client.prototype.httpGet = function (path, params, done) {
  var options = {
    params: params
  };

  this._sendHttpRequest('GET', path, options, done);
};

Client.prototype.httpPost = function (path, options, done) {
  this._sendHttpRequest('POST', path, options, done);
};

Client.prototype.httpPut = function (path, options, done) {
  this._sendHttpRequest('PUT', path, options, done);
};

Client.prototype.httpDelete = function (path, options, done) {
  this._sendHttpRequest('DELETE', path, options, done);
};
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const puppeteer = require('puppeteer')
const chalk = require('chalk')
const ms = require('ms')
const mkdirp = require('mkdirp')
const dateFormat = require('dateformat')

async function takeScreenshot(page, url) {
  await page.goto(url, { waitUntil: 'networkidle2' })
  return page.screenshot()
}

async function addScreenshot(page, argv) {
  try {
    // Ensure directory exists
    mkdirp.sync(argv.directory)

    // Get screenshot as a buffer but don't write to disk yet
    const screenshotBuffer = await takeScreenshot(page, argv._[0])

    // Read screenshots directory
    const recentFiles = fs.readdirSync(argv.directory).reverse()

    // Pick last file
    const lastFile = recentFiles[0]

    // For logging
    const now = dateFormat(Date.now(), 'hh:MM:ss')

    // Check if the last file is the same as the screenshot buffer
    if (
      lastFile &&
      fs
        // Get full path as readdir just returns file names, not full path
        .readFileSync(path.join(argv.directory, lastFile))
        .equals(screenshotBuffer)
    ) {
      // Duplicate
      console.log(chalk.gray(now, 'Duplicate screenshot, skipping'))
    } else {
      // Write screenshot to disk
      const filename = path.join(argv.directory, `${Date.now()}.png`)
      fs.writeFileSync(filename, screenshotBuffer)
      console.log(chalk.green(now, 'Screenshot saved'))
    }
  } catch (err) {
    console.log(chalk.red('Failed to take screenshot'))
    console.log(err)
  }
}

module.exports = async function(argv) {
  console.log(chalk.gray('Screenshots directory'), argv.directory)
  console.log(chalk.gray('Screenshots interval'), argv.every)
  console.log(
    chalk.gray('Page viewport'),
    argv.viewport.width,
    'x',
    argv.viewport.height
  )
  console.log(chalk.gray('URL'), argv._[0])

  const browser = await puppeteer.launch()
  const page = await browser.newPage()

  page.setViewport({
    ...argv.viewport,
    deviceScaleFactor: 2
  })

  await addScreenshot(page, argv)

  setInterval(() => addScreenshot(page, argv), ms(argv.every))
}
<commit_msg>tolerate bad ssl certificates<commit_after>const fs = require('fs')
const path = require('path')
const puppeteer = require('puppeteer')
const chalk = require('chalk')
const ms = require('ms')
const mkdirp = require('mkdirp')
const dateFormat = require('dateformat')

async function takeScreenshot(page, url) {
  await page.goto(url, { waitUntil: 'networkidle2' })
  return page.screenshot()
}

async function addScreenshot(page, argv) {
  try {
    // Ensure directory exists
    mkdirp.sync(argv.directory)

    // Get screenshot as a buffer but don't write to disk yet
    const screenshotBuffer = await takeScreenshot(page, argv._[0])

    // Read screenshots directory
    const recentFiles = fs.readdirSync(argv.directory).reverse()

    // Pick last file
    const lastFile = recentFiles[0]

    // For logging
    const now = dateFormat(Date.now(), 'hh:MM:ss')

    // Check if the last file is the same as the screenshot buffer
    if (
      lastFile &&
      fs
        // Get full path as readdir just returns file names, not full path
        .readFileSync(path.join(argv.directory, lastFile))
        .equals(screenshotBuffer)
    ) {
      // Duplicate
      console.log(chalk.gray(now, 'Duplicate screenshot, skipping'))
    } else {
      // Write screenshot to disk
      const filename = path.join(argv.directory, `${Date.now()}.png`)
      fs.writeFileSync(filename, screenshotBuffer)
      console.log(chalk.green(now, 'Screenshot saved'))
    }
  } catch (err) {
    console.log(chalk.red('Failed to take screenshot'))
    console.log(err)
  }
}

module.exports = async function(argv) {
  console.log(chalk.gray('Screenshots directory'), argv.directory)
  console.log(chalk.gray('Screenshots interval'), argv.every)
  console.log(
    chalk.gray('Page viewport'),
    argv.viewport.width,
    'x',
    argv.viewport.height
  )
  console.log(chalk.gray('URL'), argv._[0])

  const browser = await puppeteer.launch({
    ignoreHTTPSErrors: true,
    args:['--ignore-certificate-errors', '--enable-feature=NetworkService']
  })
  const page = await browser.newPage()

  page.setViewport({
    ...argv.viewport,
    deviceScaleFactor: 2
  })

  await addScreenshot(page, argv)

  setInterval(() => addScreenshot(page, argv), ms(argv.every))
}
<|endoftext|>


<commit_before>/*
 * CHECKMATES
 *
 * Ben Postlethwaite
 * 2013
 *
 * License MIT
 */

"use strict";

var EventEmitter = require('events').EventEmitter

module.exports = CheckMates

function CheckMates (groupID) {

  var group = new EventEmitter
    , checked = {}
    , checkmates = []

  function checkbox(value) {
    /*
     * Tie to DOM
     */
    var self = document.createElement('input')
    self.type = "checkbox"
    self.value = value
    self.className = groupID

    self.onclick = function () {
      if (self.checked) {
        checked[self.value] = self
        group.emit('checked', self.value)
      }  else {
        delete checked[self.value]
        group.emit('unchecked', self.value)
      }
      updateState()
    }

    checkmates.push(self)
    return self
  }

  function master(value) {
    var mastercb = checkbox(value)
    mastercb.onclick = function () {
      if (group.master.indeterminate) {
        /*
         * Clicked while indeterminate:
         * Uncheck all boxes
         */
        group.emit('unchecked', self.value)
        uncheckAll()
      } else if (group.master.checked) {
        /*
         * Wasn't indeterminate and is now checked:
         * Check all checkboxes
         */
        group.emit('checked', self.value)
        checkAll()
      } else {
        /*
         * Wasn't indeterminate but is now unchecked:
         * Uncheck all boxes
         */
        group.emit('unchecked', self.value)
        uncheckAll()
      }
    }
    group.master = mastercb

    return mastercb
  }

  function updateState () {
    if (Object.keys(checked).length === checkmates.length) {
      group.master.indeterminate = false
      group.master.checked = true
      group.emit('all-checked', true)
    }
    else if (Object.keys(checked).length === 0) {
      group.master.indeterminate = false
      group.master.checked = false
      group.emit('all-unchecked', true)
    }
    else {
      group.master.checked = true
      group.master.indeterminate = true
    }
  }

  function checkAll () {
    checkmates.forEach( function (checkbox) {
      checkbox.checked = true
      checked[checkbox.value] = checkbox
    })
    updateState()
  }

  function uncheckAll () {
    Object.keys(checked).forEach( function (key) {
      checked[key].checked = false
      delete checked[key]
    })
    updateState()
  }

  function removeAll () {
    uncheckAll()
    checkmates = []
  }

  group.removeAll = removeAll
  group.uncheckAll = uncheckAll
  group.checkAll = checkAll
  group.checkmates = checkmates
  group.checked = checked
  group.checkbox = checkbox
  group.master = master

  return group

}
<commit_msg>allow checkmates to emit optional data object<commit_after>/*
 * CHECKMATES
 *
 * Ben Postlethwaite
 * 2013
 *
 * License MIT
 */

"use strict";

var EventEmitter = require('events').EventEmitter

module.exports = CheckMates

function CheckMates (groupID) {

  var group = new EventEmitter
    , checked = {}
    , checkmates = []

  function checkbox(value, data) {
    /*
     * Tie to DOM
     */
    var self = document.createElement('input')
    self.type = "checkbox"
    self.value = value
    self.className = groupID

    self.onclick = function () {
      if (self.checked) {
        checked[self.value] = self
        group.emit('checked', self.value, data)
      }  else {
        delete checked[self.value]
        group.emit('unchecked', self.value, data)
      }
      updateState()
    }

    checkmates.push(self)
    return self
  }

  function master(value, data) {
    var mastercb = checkbox(value)
    mastercb.onclick = function () {
      if (group.master.indeterminate) {
        /*
         * Clicked while indeterminate:
         * Uncheck all boxes
         */
        group.emit('unchecked', self.value, data)
        uncheckAll()
      } else if (group.master.checked) {
        /*
         * Wasn't indeterminate and is now checked:
         * Check all checkboxes
         */
        group.emit('checked', self.value, data)
        checkAll()
      } else {
        /*
         * Wasn't indeterminate but is now unchecked:
         * Uncheck all boxes
         */
        group.emit('unchecked', self.value, data)
        uncheckAll()
      }
    }
    group.master = mastercb

    return mastercb
  }

  function updateState () {
    if (Object.keys(checked).length === checkmates.length) {
      group.master.indeterminate = false
      group.master.checked = true
      group.emit('all-checked', true)
    }
    else if (Object.keys(checked).length === 0) {
      group.master.indeterminate = false
      group.master.checked = false
      group.emit('all-unchecked', true)
    }
    else {
      group.master.checked = true
      group.master.indeterminate = true
    }
  }

  function checkAll () {
    checkmates.forEach( function (checkbox) {
      checkbox.checked = true
      checked[checkbox.value] = checkbox
    })
    updateState()
  }

  function uncheckAll () {
    Object.keys(checked).forEach( function (key) {
      checked[key].checked = false
      delete checked[key]
    })
    updateState()
  }

  function removeAll () {
    uncheckAll()
    checkmates = []
  }

  group.removeAll = removeAll
  group.uncheckAll = uncheckAll
  group.checkAll = checkAll
  group.checkmates = checkmates
  group.checked = checked
  group.checkbox = checkbox
  group.master = master

  return group

}
<|endoftext|>


<commit_before>/* eslint no-console:0 */
import {
  List, Collapse, Flex, WingBlank, WhiteSpace, InputItem, Checkbox, Radio,
  TextareaItem, Switch, Button, ListPicker,
  ListDatePicker, SelectList, SearchBar, Process, Progress,
  TopNotice, Tabs, Modal, Toast, Alert,
  PageResult, ActionSheet, Dropdown, FloatMenu, Badge, Tag, Drawer, NavBar,
  RefreshControl
} from 'antm';

// copy from above
export {
  List, Collapse, Flex, WingBlank, WhiteSpace, InputItem, Checkbox, Radio,
  TextareaItem, Switch, Button, ListPicker,
  ListDatePicker, SelectList, SearchBar, Process, Progress,
  TopNotice, Tabs, Modal, Toast, Alert,
  PageResult, ActionSheet, Dropdown, FloatMenu, Badge, Tag, Drawer, NavBar,
  RefreshControl
};

if (typeof console !== 'undefined' && console.warn) {
  console.warn(`you are using prebuild antm,
please use https://github.com/ant-design/babel-plugin-antd to reduce app bundle size.`);
}
<commit_msg>fix index<commit_after>/* eslint no-console:0 */

function camelCase(name) {
  return name.charAt(0).toUpperCase() +
    name.slice(1).replace(/-(\w)/g, (m, n) => {
      return n.toUpperCase();
    });
}

const req = require.context('./components', true, /^\.\/[^_][\w-]+\/(style\/)?index\.jsx?$/);

req.keys().forEach((mod) => {
  const v = req(mod);
  const match = mod.match(/^\.\/([^_][\w-]+)\/index\.jsx?$/);
  if (match && match[1]) {
    exports[camelCase(match[1])] = v;
  }
});

if (typeof console !== 'undefined' && console.warn) {
  console.warn(`you are using prebuild antm,
please use https://github.com/ant-design/babel-plugin-antd to reduce app bundle size.`);
}
<|endoftext|>


<commit_before>'use strict';

var path = require('path');

var sourceMap = require('source-map');
var convertSourceMap = require('convert-source-map');

var SourceMapGenerator = sourceMap.SourceMapGenerator;
var SourceMapConsumer = sourceMap.SourceMapConsumer;

/**
 * @param {string} filePath
 * @param {string} contents
 * @param {{sourceMaps: boolean, inputSourceMap: object, basePath: string}=} config
 * @returns {{contents: string, sourceMap: (undefined|object)}}
 */
function wrapIife(filePath, contents, config) {
    var sourceMaps = config && config.sourceMaps || false;
    var inputSourceMap = config && config.inputSourceMap;
    var basePath = config && config.basePath || '.';

    var iifeBegin = '!(function() { ';
    var iifeEnd = '}());';

    var map = new SourceMapGenerator();

    var sourceRelativePath = path.relative(basePath, filePath);

    map.addMapping({
        source: sourceRelativePath,
        original: {line: 1, column: 0},
        generated: {line: 1, column: iifeBegin.length}
    });

    var lineNumber = 2;
    var newLineIndexOf;

    newLineIndexOf = contents.indexOf('\n', 0);
    while (newLineIndexOf !== -1) {
        map.addMapping({
            source: sourceRelativePath,
            original: {line: lineNumber, column: 0},
            generated: {line: lineNumber, column: 0}
        });

        lineNumber++;
        newLineIndexOf = contents.indexOf('\n', newLineIndexOf + 1);
    }

    var modifiedContents = inputSourceMap ? convertSourceMap.removeComments(contents) : contents;

    var lastCharacter = modifiedContents[modifiedContents.length - 1];

    modifiedContents = iifeBegin + modifiedContents + (lastCharacter !== '\n' ? '\n' : '') + iifeEnd;

    map.applySourceMap(new SourceMapConsumer(inputSourceMap));

    return {contents: modifiedContents, sourceMap: sourceMaps ? JSON.parse(map.toString()) : null};
}

module.exports = wrapIife;
<commit_msg>REVERT: Now uses SourceMapGenerator#applySourceMap to apply the input source map; this fixes a glitch in the coverage reporting causing a `'use strict';` on the first line to be reported as covered.<commit_after>'use strict';

var path = require('path');

var sourceMap = require('source-map');
var convertSourceMap = require('convert-source-map');

var SourceMapGenerator = sourceMap.SourceMapGenerator;
var SourceMapConsumer = sourceMap.SourceMapConsumer;

/**
 * @param {string} filePath
 * @param {string} contents
 * @param {{sourceMaps: boolean, inputSourceMap: object, basePath: string}=} config
 * @returns {{contents: string, sourceMap: (undefined|object)}}
 */
function wrapIife(filePath, contents, config) {
    var sourceMaps = config && config.sourceMaps || false;
    var inputSourceMap = config && config.inputSourceMap;
    var basePath = config && config.basePath || '.';

    var iifeBegin = '!(function() { ';
    var iifeEnd = '}());';

    var map = inputSourceMap ? SourceMapGenerator.fromSourceMap(new SourceMapConsumer(inputSourceMap)) :
            new SourceMapGenerator();

    var sourceRelativePath = path.relative(basePath, filePath);

    map.addMapping({
        source: sourceRelativePath,
        original: {line: 1, column: 0},
        generated: {line: 1, column: iifeBegin.length}
    });

    var lineNumber = 2;
    var newLineIndexOf;

    newLineIndexOf = contents.indexOf('\n', 0);
    while (newLineIndexOf !== -1) {
        map.addMapping({
            source: sourceRelativePath,
            original: {line: lineNumber, column: 0},
            generated: {line: lineNumber, column: 0}
        });

        lineNumber++;
        newLineIndexOf = contents.indexOf('\n', newLineIndexOf + 1);
    }

    var modifiedContents = inputSourceMap ? convertSourceMap.removeComments(contents) : contents;

    var lastCharacter = modifiedContents[modifiedContents.length - 1];

    modifiedContents = iifeBegin + modifiedContents + (lastCharacter !== '\n' ? '\n' : '') + iifeEnd;

    return {contents: modifiedContents, sourceMap: sourceMaps ? JSON.parse(map.toString()) : null};
}

module.exports = wrapIife;
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var stack = require('simple-stack-common');
var envs = require('envs');
var assets = require('simple-assets');
var oauth = require('./lib/oauth');

/**
 * Forwarding headers
 */

var headers = {
  host: 'x-orig-host',
  path: 'x-orig-path',
  port: 'x-orig-port',
  proto: 'x-orig-proto'
};

/**
 * Expose the app
 */

exports = module.exports = function(opts) {
  opts = opts || {};

  var root = opts.root || process.cwd();
  var restricted = opts.restricted;
  var CDN_URL = opts.cdn || envs('CDN_URL') || '';
  var STATIC_MAX_AGE = opts.staticMaxAge || envs.int('STATIC_MAX_AGE', 0);
  var API_URL = opts.apiUrl || envs('API_URL');
  var SITE_URL = opts.siteUrl || envs('SITE_URL');
  var ENABLED_FEATURES = opts.enabledFeatures || envs('ENABLED_FEATURES') || '';

  // Load in the routes
  if (!opts.routes) {
    try {
      opts.routes = require(root + '/public/javascripts/routes');
    } catch (e) {
      opts.routes = {'/': 'index'};
    }
  }
  var routes = Object.keys(opts.routes);

  // Load the package.json
  var package = {};
  try {
    package = require(root + '/package.json');
  } catch (e) {}

  function assetLookup(file, path, useCdn) {
    return (useCdn ? CDN_URL : '') + path + '/' + assets(file);
  }

  // TODO allow adding scripts and styles

  var styles = function(min, path) {
    return [
      assetLookup(min ? 'build/style.min.css' : 'build/style.css', path, min)
    ];
  }

  var scripts = function(min, path) {
    return [
      assetLookup(min ? 'build/require.min.js' : 'build/require.js', path, min),
      assetLookup(min ? 'build/vendor.min.js' : 'build/vendor.js', path, min),
      assetLookup(min ? 'build/app.min.js' : 'build/app.js', path, min)
    ];
  }

  /**
   * Create an app
   */

  var app = stack({
    base: headers
  });

  /**
   * Use jade as the default view engine
   */

  app.set('view engine', 'jade');
  app.engine('jade', require('jade').__express);

  /**
   * Set locals defauls
   */

  app.locals({
    app: package.name,
    description: package.description,
    author: package.author,
    env: {
      BROWSER_ENV: envs('NODE_ENV', 'production')
    }
  });

  /**
   * Expose a way to set browser env variables
   */

  app.env = function(key, value) {
    app.locals.env[key] = value;
    return app;
  };

  /**
   * Extra middleware
   */

  app.useBefore('router', stack.middleware.cookieParser());

  /**
   * Serve the static assets
   */

  app.useBefore('router', '/build', 'build', stack.middleware.static(root + '/build', {
    maxAge: STATIC_MAX_AGE
  }));

  app.useBefore('router', function assetLocals(req, res, next) {
    var min = req.get('x-env') === 'production';
    var path = req.get('x-orig-path') || '';

    res.locals({
      styles: styles(min, path),
      scripts: scripts(min, path),
      noscriptRedirect: !req.cookies.noscript
    });
    next();
  });

  // Proxy the api
  var proxy = require('simple-http-proxy');
  if (API_URL) app.useBefore('base', '/api', 'api-proxy', proxy(API_URL, {xforward: headers}));

  /**
   * Use authentication middleware
   */

  var auth = oauth(opts.auth);
  app.useBefore('router', '/auth/login', 'auth:login', auth.login());
  app.useBefore('router', '/auth/register', 'auth:register', auth.login({register: 1}));
  app.useBefore('router', '/auth/callback', 'auth:callback', auth.login());
  app.useBefore('router', '/auth/logout', 'auth:logout', auth.logout());
  app.useBefore('router', '/auth', 'auth:root-redirect', function(req, res) {
    res.redirect(req.base);
  });

  /**
   * Set enabled feature flags
   */

  app.useBefore('router', '/', 'features', function(req, res, next) {
    if (req.get('x-env') !== 'production') return next();
    if (ENABLED_FEATURES !== req.cookies.features) res.cookie('features', ENABLED_FEATURES);
    next();
  });

  /**
   * Remove the middleware we don't need
   */

  app.remove('methodOverride');
  app.remove('json');
  app.remove('urlencoded');

  app.get('/noscript', function(req, res) {
    res.cookie('noscript', '1');
    res.render('noscript');
  });

  /**
   * Serve an error page for any unrecoverable errors on the client
   */

  app.get('/_error', function(req, res) {
    res.render('error', function(err, body) {
      if (!err) return res.send(body);
      res.render(__dirname + '/views/error');
    });
  });

  /**
   * Mount the routes
   */

  routes.forEach(function(route) {
    app.get(route, index);
  });

  /**
   * Index
   */

  function index(req, res, next){
    // If we don't have the site url set, get it from the header or env
    if (!res.locals.site) res.locals.site = req.get('x-ui-url') || SITE_URL || req.base;

    // Expose the base url to the view
    res.locals.base = req.base;

    auth.authenticate(restricted)(req, res, function(err) {
      if (err) return next(err);

      // TODO send dns-prefetch the api and cdn

      res.render(app.get('index view') || 'index');
    });
  };

  return app;
};

/**
 * Expose the middleware
 */

stack.middleware(exports.middleware = {});
<commit_msg>minify html in production<commit_after>/**
 * Module dependencies
 */

var stack = require('simple-stack-common');
var envs = require('envs');
var assets = require('simple-assets');
var oauth = require('./lib/oauth');

/**
 * Forwarding headers
 */

var headers = {
  host: 'x-orig-host',
  path: 'x-orig-path',
  port: 'x-orig-port',
  proto: 'x-orig-proto'
};

/**
 * Expose the app
 */

exports = module.exports = function(opts) {
  opts = opts || {};

  var root = opts.root || process.cwd();
  var restricted = opts.restricted;
  var CDN_URL = opts.cdn || envs('CDN_URL') || '';
  var STATIC_MAX_AGE = opts.staticMaxAge || envs.int('STATIC_MAX_AGE', 0);
  var API_URL = opts.apiUrl || envs('API_URL');
  var SITE_URL = opts.siteUrl || envs('SITE_URL');
  var ENABLED_FEATURES = opts.enabledFeatures || envs('ENABLED_FEATURES') || '';

  // Load in the routes
  if (!opts.routes) {
    try {
      opts.routes = require(root + '/public/javascripts/routes');
    } catch (e) {
      opts.routes = {'/': 'index'};
    }
  }
  var routes = Object.keys(opts.routes);

  // Load the package.json
  var package = {};
  try {
    package = require(root + '/package.json');
  } catch (e) {}

  function assetLookup(file, path, useCdn) {
    return (useCdn ? CDN_URL : '') + path + '/' + assets(file);
  }

  // TODO allow adding scripts and styles

  var styles = function(min, path) {
    return [
      assetLookup(min ? 'build/style.min.css' : 'build/style.css', path, min)
    ];
  }

  var scripts = function(min, path) {
    return [
      assetLookup(min ? 'build/require.min.js' : 'build/require.js', path, min),
      assetLookup(min ? 'build/vendor.min.js' : 'build/vendor.js', path, min),
      assetLookup(min ? 'build/app.min.js' : 'build/app.js', path, min)
    ];
  }

  /**
   * Create an app
   */

  var app = stack({
    base: headers
  });

  /**
   * Use jade as the default view engine
   */

  app.set('view engine', 'jade');
  app.engine('jade', require('jade').__express);

  /**
   * Set locals defauls
   */

  app.locals({
    app: package.name,
    description: package.description,
    author: package.author,
    env: {
      BROWSER_ENV: envs('NODE_ENV', 'production')
    }
  });

  /**
   * Expose a way to set browser env variables
   */

  app.env = function(key, value) {
    app.locals.env[key] = value;
    return app;
  };

  /**
   * Extra middleware
   */

  app.useBefore('router', stack.middleware.cookieParser());

  /**
   * Serve the static assets
   */

  app.useBefore('router', '/build', 'build', stack.middleware.static(root + '/build', {
    maxAge: STATIC_MAX_AGE
  }));

  app.useBefore('router', function assetLocals(req, res, next) {
    var min = req.get('x-env') === 'production';
    var path = req.get('x-orig-path') || '';

    res.locals({
      styles: styles(min, path),
      scripts: scripts(min, path),
      noscriptRedirect: !req.cookies.noscript,
      pretty: !min
    });
    next();
  });

  // Proxy the api
  var proxy = require('simple-http-proxy');
  if (API_URL) app.useBefore('base', '/api', 'api-proxy', proxy(API_URL, {xforward: headers}));

  /**
   * Use authentication middleware
   */

  var auth = oauth(opts.auth);
  app.useBefore('router', '/auth/login', 'auth:login', auth.login());
  app.useBefore('router', '/auth/register', 'auth:register', auth.login({register: 1}));
  app.useBefore('router', '/auth/callback', 'auth:callback', auth.login());
  app.useBefore('router', '/auth/logout', 'auth:logout', auth.logout());
  app.useBefore('router', '/auth', 'auth:root-redirect', function(req, res) {
    res.redirect(req.base);
  });

  /**
   * Set enabled feature flags
   */

  app.useBefore('router', '/', 'features', function(req, res, next) {
    if (req.get('x-env') !== 'production') return next();
    if (ENABLED_FEATURES !== req.cookies.features) res.cookie('features', ENABLED_FEATURES);
    next();
  });

  /**
   * Remove the middleware we don't need
   */

  app.remove('methodOverride');
  app.remove('json');
  app.remove('urlencoded');

  app.get('/noscript', function(req, res) {
    res.cookie('noscript', '1');
    res.render('noscript');
  });

  /**
   * Serve an error page for any unrecoverable errors on the client
   */

  app.get('/_error', function(req, res) {
    res.render('error', function(err, body) {
      if (!err) return res.send(body);
      res.render(__dirname + '/views/error');
    });
  });

  /**
   * Mount the routes
   */

  routes.forEach(function(route) {
    app.get(route, index);
  });

  /**
   * Index
   */

  function index(req, res, next){
    // If we don't have the site url set, get it from the header or env
    if (!res.locals.site) res.locals.site = req.get('x-ui-url') || SITE_URL || req.base;

    // Expose the base url to the view
    res.locals.base = req.base;

    auth.authenticate(restricted)(req, res, function(err) {
      if (err) return next(err);

      // TODO send dns-prefetch the api and cdn

      res.render(app.get('index view') || 'index');
    });
  };

  return app;
};

/**
 * Expose the middleware
 */

stack.middleware(exports.middleware = {});
<|endoftext|>


<commit_before>function spawn(genFunc) {
  var generator = genFunc();
  function co(type, arg) {
    var res;
    try {
      res = generator[type](arg);
    } catch (e) {
      return Promise.reject(e);
    }
    if (res.done) {
      if (type === 'throw') {
        return arg;
      } else {
        return res.value;
      }
    } else {
      return Promise.resolve(res.value)
      .then(function (val) {
        return co('next', val);
      }, function (err) {
        return co('throw', err);
      });
    }
  }
  co('next');
}

module.exports = spawn;
<commit_msg>copied from internet<commit_after>function spawn(genFunc) {
  var generator = genFunc();
  function co(type, arg) {
    var res;
    try {
      res = generator[type](arg);
    } catch (e) {
      return Promise.reject(e);
    }
    if (res.done) {
      if (type === 'throw') {
        return arg;
      } else {
        return res.value;
      }
    } else {
      return Promise.resolve(res.value)
      .then(function (val) {
        return co('next', val);
      }, function (err) {
        return co('throw', err);
      });
    }
  }
  return Promise.resolve(co('next'));
}

module.exports = spawn;
<|endoftext|>


<commit_before>'use strict';

// ### design
//  commander({
//      commands: './lib/command',
//      options: './opt/',
//      name: 'cortex'
//  }).cli();
module.exports = comfort;
comfort.Comfort = Comfort;

function comfort (options) {
    return new Comfort(options);
}

var DEFAULT_EVENTS = {
    plugin: function(e) {
        this.logger.info(
            this.logger.template('{{name}}: "{{command}}" is not a {{name}} command. See "{{name}} --help".', {
                name: e.name,
                command: e.command
            })
        );
    },

    complete: function(e) {
        var err = e.err;

        if(err){
            if ( err instanceof Error ) {
                // loggie will deal with `Error` instances
                this.logger.error(err)

            // error code
            } else if (typeof err === 'number') {
                this.logger.error('Not ok, exit code: ' + err);

            } else {
                this.logger.error( err.message || err );
            }

        }else if(e.command !== 'help'){
            this.logger.info('{{green OK!}}');
        }
    }
};

var node_path   = require('path');
var EE          = require('events').EventEmitter;
var node_util   = require('util');
var node_spawn  = require('child_process').spawn;
var node_fs     = require('fs');

var clean       = require('clean');

var builtin_command_root = node_path.join( __dirname, 'lib', 'built-in', 'command' );
var builtin_option_root = node_path.join( __dirname, 'lib', 'built-in', 'option' );

var exists = node_fs.existsSync ?
    function (file) {
        return node_fs.existsSync(file);
    } :

    // if node <= 0.6, there's no fs.existsSync method.
    function (file) {
        try {
            node_fs.statSync(file);
            return true;
        } catch(e) {
            return false;
        }
    };

function isFile (file) {
    return node_fs.statSync(file).isFile();
}

function Comfort(options){
    this.options = options = options || {};
    this.logger = options.logger || require('loggie')();
    this.context = options.context || {};

    options.offset = 'offset' in options ? options.offset : 3;
    // options.default_command = options.default_command || 'help';

    this.__commander = {};
}

node_util.inherits(Comfort, EE);

// # Design spec

// ## method to run in cli (bin):
// - .cli()

// Should:
// - driven by events

// ## method used by users or utility methods:
// - .run(),
// - .command_exists(),
// - .get_commander()

// Should:
// - driven by callbacks
// - handle errors with node-favored async way

// ****

// # Events:
// ## plugin
// {
//     name: {string},
//     command: {string} plugin name,
//     args: {Array}
// }

// ## complete
// {
//     name   : {string}
//     command: {string} command name
//     err    : {mixed}
//     data   : []
// }

// run cli
Comfort.prototype.cli = function(argv) {
    var self = this;

    argv = argv || process.argv;

    this.parse(argv, function(err, result, details){
        var command = result.command;
        var opt = result.opt;

        self.run(command, opt, function (err) {
            if ( err && err.code === 'E_COMMAND_NOT_FOUND') {
                return self._run_plugin(command, argv.slice(self.options.offset), function(){
                    self._cli_complete(command, arguments)
                });
            }

            self._cli_complete(command, arguments);
        });
    });
};

Comfort.prototype._cli_complete = function (command, args) {
    args = Array.prototype.slice.call(args);
    var error = args.shift();

    this._emit('complete', {
        name   : this.options.name,
        command: command,
        err    : error,
        data   : args
    });
};

// Try to run the given command from the `PATH`
Comfort.prototype._run_plugin = function(command, args, callback) {
    var name = this.options.name;
    var bin = name + '-' + command;
    var paths = process.env.PATH.split(':');
    var found;

    paths.some(function (path) {
        var bin_path = node_path.resolve(path, bin);

        if ( exists(bin_path) && isFile(bin_path) ) {
            found = bin_path;
            return true;
        }
    });

    if ( !found ) {
        return this._command_not_found(command, callback);
    }

    this._emit('plugin', {
        name: name,
        command: command,
        args: args
    });

    var plugin = node_spawn(found, args, {
        stdio: 'inherit',
        // `options.customFds` is now DEPRECATED.
        // just for backward compatibility.
        customFds: [0, 1, 2]
    });

    plugin.on('close', function(code){
        callback(code);
    });
};

Comfort.prototype._command_not_found = function(command, callback) {
    var name = this.options.name;
    callback({
        code: 'E_COMMAND_NOT_FOUND',
        message: '"' + command + '" is not a ' + name + ' command',
        data: {
            name: name,
            command: command
        }
    });
};

// ＠public
// Run a command with callbacks.
// This method might be called manually.
Comfort.prototype.run = function (command, options, callback) {
    var commander = this.get_commander(command);
    var name = this.options.name;

    // explode `comfort` options to sub commands
    if(command === 'help'){
        options.options = this.options;
    }

    if ( !commander ) {
        this._command_not_found(command, callback);

    } else {
        this._run_commander(commander, options, callback);
    }
};

// Run a given commander
Comfort.prototype._run_commander = function (commander, options, callback) {
    commander.run(options, callback);
};

// parse a specified argument vector
// @param {function()} callback
Comfort.prototype.parse = function(argv, callback) {

    // argv ->
    // ['node', __dirname, '<command>', ...]
    var command;
    var index_h = argv.indexOf('-h');
    var index_help = argv.indexOf('--help');

    // 'help' command need special treatment
    if(
        // ctx -h
        index_h > 0 ||
        // ctx --help
        index_help > 0 ||
        // ctx
        // root command will be help command
        argv.length === 2
    ){
        // 1   2       3
        // ctx install -h
        // ctx install --help
        // -> ctx help --command install --no-detail
        var command_for_help = index_h !== 2 && index_help !== 2 && argv[2];

        callback(null, {
            command: 'help',
            opt: {
                // ctx
                // -> ctx help --command * --no-detail
                command: command_for_help || '*',

                // if there's only root command, an `entrance` option will be added
                entrance: argv.length === 2
            }
        });

    // normal command
    } else {
        command = argv[2];
        var parsed;

        var opt_file = this._get_option_file(command);
        var opt_rules;

        if ( opt_file ) {
            var rule = require(opt_file);

            clean({
                schema: rule.options,
                shorthands: rule.shorthands,
                offset: this._offset

            }).parseArgv(argv, function (err, results, details) {
                callback(err, {
                    command: command,
                    opt: results
                }, details);
            });

        // if no opt_rule matches
        } else {
            callback(null, {
                command: command,
                opt: {}
            });
        }
    }
};

// check if a sub commander
Comfort.prototype.command_exists = function (command) {
    return !!this._get_commander_file(command);
};

// @returns {Object|false}
Comfort.prototype.get_commander = function (command) {
    // cache commander to improve performance
    var commander = this.__commander[command];

    if(!commander){
        var commander_file = this._get_commander_file(command);

        if(!commander_file){
            return false;
        }

        commander = require(commander_file);

        // There might be more than one comfort instances,
        // so `Object.create` a new commander object to prevent reference pollution.
        this.__commander[command] = Object.create(commander);

        commander.context = this.context;
        commander.logger  = this.logger;
    }

    return commander;
};

Comfort.prototype._callback_handler = function(command) {
    var self = this;

    return function() {
        var args = Array.prototype.slice.call(arguments);
        var error = args.shift();

        self._emit('complete', {
            name   : self.options.name,
            command: command,
            err    : error && (error.stack || error.message || error.error || error),
            data   : args
        });
    }
};

// ._emit('COMMAND_NOT_FOUND', command)
Comfort.prototype._emit = function(type, data) {
    if(!type){
        return;
    }

    // if there is no custom event listeners
    if( EE.listenerCount(this, type) === 0 ){
        DEFAULT_EVENTS[type].apply(this, Array.prototype.slice.call(arguments, 1) );
    }else{
        // this.emit('commandNotFound', command)
        this.emit.apply(this, arguments);
    }
};

// @param {string} command name of the command
// @returns
//      {false} if commander not found
//      {path} path of the commander file
Comfort.prototype._get_commander_file = function(command) {
    return !!command && (
        this._get_file(this.options.command_root, command) ||
        command === 'help' && this._get_file(builtin_command_root, command)
    );
};

Comfort.prototype._get_option_file = function(command) {
    return !!command && (
        this._get_file(this.options.option_root, command) ||
        command === 'help' && this._get_file(builtin_option_root, command)
    );
};

Comfort.prototype._get_file = function(root, name) {
    var file = node_path.join( root, name + '.js' );

    return exists(file) && file;
};

<commit_msg>fixes #8: fix the error message of argv<commit_after>'use strict';

// ### design
//  commander({
//      commands: './lib/command',
//      options: './opt/',
//      name: 'cortex'
//  }).cli();
module.exports = comfort;
comfort.Comfort = Comfort;

function comfort (options) {
    return new Comfort(options);
}

var DEFAULT_EVENTS = {
    plugin: function(e) {
        this.logger.info(
            this.logger.template('{{name}}: "{{command}}" is not a {{name}} command. See "{{name}} --help".', {
                name: e.name,
                command: e.command
            })
        );
    },

    complete: function(e) {
        var err = e.err;

        if(err){
            if ( err instanceof Error ) {
                // loggie will deal with `Error` instances
                this.logger.error(err)

            // error code
            } else if (typeof err === 'number') {
                this.logger.error('Not ok, exit code: ' + err);

            } else {
                this.logger.error( err.message || err );
            }

        }else if(e.command !== 'help'){
            this.logger.info('{{green OK!}}');
        }
    }
};

var node_path   = require('path');
var EE          = require('events').EventEmitter;
var node_util   = require('util');
var node_spawn  = require('child_process').spawn;
var node_fs     = require('fs');

var clean       = require('clean');

var builtin_command_root = node_path.join( __dirname, 'lib', 'built-in', 'command' );
var builtin_option_root = node_path.join( __dirname, 'lib', 'built-in', 'option' );

var exists = node_fs.existsSync ?
    function (file) {
        return node_fs.existsSync(file);
    } :

    // if node <= 0.6, there's no fs.existsSync method.
    function (file) {
        try {
            node_fs.statSync(file);
            return true;
        } catch(e) {
            return false;
        }
    };

function isFile (file) {
    return node_fs.statSync(file).isFile();
}

function Comfort(options){
    this.options = options = options || {};
    this.logger = options.logger || require('loggie')();
    this.context = options.context || {};

    options.offset = 'offset' in options ? options.offset : 3;
    // options.default_command = options.default_command || 'help';

    this.__commander = {};
}

node_util.inherits(Comfort, EE);

// # Design spec

// ## method to run in cli (bin):
// - .cli()

// Should:
// - driven by events

// ## method used by users or utility methods:
// - .run(),
// - .command_exists(),
// - .get_commander()

// Should:
// - driven by callbacks
// - handle errors with node-favored async way

// ****

// # Events:
// ## plugin
// {
//     name: {string},
//     command: {string} plugin name,
//     args: {Array}
// }

// ## complete
// {
//     name   : {string}
//     command: {string} command name
//     err    : {mixed}
//     data   : []
// }

// run cli
Comfort.prototype.cli = function(argv) {
    var self = this;

    argv = argv || process.argv;

    this.parse(argv, function(err, result, details){
        var command = result.command;
        var opt = result.opt;

        if ( err ) {
            return self._cli_complete(command, [err]);
        }

        self.run(command, opt, function (err) {
            if ( err && err.code === 'E_COMMAND_NOT_FOUND') {
                return self._run_plugin(command, argv.slice(self.options.offset), function(){
                    self._cli_complete(command, arguments)
                });
            }

            self._cli_complete(command, arguments);
        });
    });
};

Comfort.prototype._cli_complete = function (command, args) {
    args = Array.prototype.slice.call(args);
    var error = args.shift();

    this._emit('complete', {
        name   : this.options.name,
        command: command,
        err    : error,
        data   : args
    });
};

// Try to run the given command from the `PATH`
Comfort.prototype._run_plugin = function(command, args, callback) {
    var name = this.options.name;
    var bin = name + '-' + command;
    var paths = process.env.PATH.split(':');
    var found;

    paths.some(function (path) {
        var bin_path = node_path.resolve(path, bin);

        if ( exists(bin_path) && isFile(bin_path) ) {
            found = bin_path;
            return true;
        }
    });

    if ( !found ) {
        return this._command_not_found(command, callback);
    }

    this._emit('plugin', {
        name: name,
        command: command,
        args: args
    });

    var plugin = node_spawn(found, args, {
        stdio: 'inherit',
        // `options.customFds` is now DEPRECATED.
        // just for backward compatibility.
        customFds: [0, 1, 2]
    });

    plugin.on('close', function(code){
        callback(code);
    });
};

Comfort.prototype._command_not_found = function(command, callback) {
    var name = this.options.name;
    callback({
        code: 'E_COMMAND_NOT_FOUND',
        message: '"' + command + '" is not a ' + name + ' command',
        data: {
            name: name,
            command: command
        }
    });
};

// ＠public
// Run a command with callbacks.
// This method might be called manually.
Comfort.prototype.run = function (command, options, callback) {
    var commander = this.get_commander(command);
    var name = this.options.name;

    // explode `comfort` options to sub commands
    if(command === 'help'){
        options.options = this.options;
    }

    if ( !commander ) {
        this._command_not_found(command, callback);

    } else {
        this._run_commander(commander, options, callback);
    }
};

// Run a given commander
Comfort.prototype._run_commander = function (commander, options, callback) {
    commander.run(options, callback);
};

// parse a specified argument vector
// @param {function()} callback
Comfort.prototype.parse = function(argv, callback) {

    // argv ->
    // ['node', __dirname, '<command>', ...]
    var command;
    var index_h = argv.indexOf('-h');
    var index_help = argv.indexOf('--help');

    // 'help' command need special treatment
    if(
        // ctx -h
        index_h > 0 ||
        // ctx --help
        index_help > 0 ||
        // ctx
        // root command will be help command
        argv.length === 2
    ){
        // 1   2       3
        // ctx install -h
        // ctx install --help
        // -> ctx help --command install --no-detail
        var command_for_help = index_h !== 2 && index_help !== 2 && argv[2];

        callback(null, {
            command: 'help',
            opt: {
                // ctx
                // -> ctx help --command * --no-detail
                command: command_for_help || '*',

                // if there's only root command, an `entrance` option will be added
                entrance: argv.length === 2
            }
        });

    // normal command
    } else {
        command = argv[2];
        var parsed;

        var opt_file = this._get_option_file(command);
        var opt_rules;

        if ( opt_file ) {
            var rule = require(opt_file);

            clean({
                schema: rule.options,
                shorthands: rule.shorthands,
                offset: this._offset

            }).parseArgv(argv, function (err, results, details) {
                callback(err, {
                    command: command,
                    opt: results
                }, details);
            });

        // if no opt_rule matches
        } else {
            callback(null, {
                command: command,
                opt: {}
            });
        }
    }
};

// check if a sub commander
Comfort.prototype.command_exists = function (command) {
    return !!this._get_commander_file(command);
};

// @returns {Object|false}
Comfort.prototype.get_commander = function (command) {
    // cache commander to improve performance
    var commander = this.__commander[command];

    if(!commander){
        var commander_file = this._get_commander_file(command);

        if(!commander_file){
            return false;
        }

        commander = require(commander_file);

        // There might be more than one comfort instances,
        // so `Object.create` a new commander object to prevent reference pollution.
        this.__commander[command] = Object.create(commander);

        commander.context = this.context;
        commander.logger  = this.logger;
    }

    return commander;
};

Comfort.prototype._callback_handler = function(command) {
    var self = this;

    return function() {
        var args = Array.prototype.slice.call(arguments);
        var error = args.shift();

        self._emit('complete', {
            name   : self.options.name,
            command: command,
            err    : error && (error.stack || error.message || error.error || error),
            data   : args
        });
    }
};

// ._emit('COMMAND_NOT_FOUND', command)
Comfort.prototype._emit = function(type, data) {
    if(!type){
        return;
    }

    // if there is no custom event listeners
    if( EE.listenerCount(this, type) === 0 ){
        DEFAULT_EVENTS[type].apply(this, Array.prototype.slice.call(arguments, 1) );
    }else{
        // this.emit('commandNotFound', command)
        this.emit.apply(this, arguments);
    }
};

// @param {string} command name of the command
// @returns
//      {false} if commander not found
//      {path} path of the commander file
Comfort.prototype._get_commander_file = function(command) {
    return !!command && (
        this._get_file(this.options.command_root, command) ||
        command === 'help' && this._get_file(builtin_command_root, command)
    );
};

Comfort.prototype._get_option_file = function(command) {
    return !!command && (
        this._get_file(this.options.option_root, command) ||
        command === 'help' && this._get_file(builtin_option_root, command)
    );
};

Comfort.prototype._get_file = function(root, name) {
    var file = node_path.join( root, name + '.js' );

    return exists(file) && file;
};

<|endoftext|>


<commit_before>const axios = require('axios')
const md5 = require('md5')
const { GLOBAL_CONFIG } = require('./config')

const __emit__ = function({ path, username, appname, createdAt, uuid, request, response, logger, labels = [], save }) {
  return axios.post(path, {
    username, appname, createdAt, uuid, request, response, logger, labels, save
  })
}

// 自动创建 createdAt
const _emit = function({ path, username, appname, uuid, labels = [] }, save) {
  return function({ request, response, logger }) {
    const createdAt = new Date()
    return __emit__({ path, username, appname, createdAt, uuid, request, response, logger, labels, save })
  }
}

// 传递 path username appname labels
// 自动创建 uuid
const watcher = function(params={}) {
  let { origin, username, appname, labels = [], save } = params

  const uuid = md5(new Date().toString() + Math.random())

  origin = origin || GLOBAL_CONFIG.origin
  username = username || GLOBAL_CONFIG.username
  appname = appname || GLOBAL_CONFIG.appname
  labels = labels || GLOBAL_CONFIG.labels
  save = save || GLOBAL_CONFIG.save

  const path = origin + '/receiver'

  return {
    emitReq: function(request) {
      let { url, headers, params, method } = request
      request = { url, headers, params, method }
      return _emit({ path, username, appname, uuid, labels })({ request })
    },
    emitRes: function(response) {
      let { status, data, headers } = response
      response = { status, data, headers }
      return _emit({ path, username, appname, uuid, labels })({ response })
    },
    emitLog: function(logger) {
      let { title, content } = logger
      logger = { title, content }
      return _emit({ path, username, appname, uuid, labels })({ logger })
    }
  }
}

// 将 watcher.global 作为一个 config 收集器
watcher.global = GLOBAL_CONFIG

// Logger
watcher.logger = function(title, content) {
  if (!content) {
    content = title
  }
  title = title.toString()
  const { emitLog } = watcher()
  emitLog({ title, content })
}

watcher.use = function (watcherFunc) {
  if (typeof watcherFunc === 'function') {
    watcherFunc(watcher)
  } else {
    throw new Error('Given arg is not supported')
  }
}

module.exports = watcher<commit_msg>fix bug<commit_after>const axios = require('axios')
const md5 = require('md5')
const { GLOBAL_CONFIG } = require('./config')

const __emit__ = function({ path, username, appname, createdAt, uuid, request, response, logger, labels = [], save }) {
  return axios.post(path, {
    username, appname, createdAt, uuid, request, response, logger, labels, save
  })
}

// 自动创建 createdAt
const _emit = function({ path, username, appname, uuid, labels = [], save}) {
  return function({ request, response, logger }) {
    const createdAt = new Date()
    return __emit__({ path, username, appname, createdAt, uuid, request, response, logger, labels, save })
  }
}

// 传递 path username appname labels
// 自动创建 uuid
const watcher = function(params={}) {
  let { origin, username, appname, labels = [], save } = params

  const uuid = md5(new Date().toString() + Math.random())

  origin = origin || GLOBAL_CONFIG.origin
  username = username || GLOBAL_CONFIG.username
  appname = appname || GLOBAL_CONFIG.appname
  labels = labels || GLOBAL_CONFIG.labels
  save = save || GLOBAL_CONFIG.save

  const path = origin + '/receiver'

  return {
    emitReq: function(request) {
      let { url, headers, params, method } = request
      request = { url, headers, params, method }
      return _emit({ path, username, appname, uuid, labels, save })({ request })
    },
    emitRes: function(response) {
      let { status, data, headers } = response
      response = { status, data, headers }
      return _emit({ path, username, appname, uuid, labels, save })({ response })
    },
    emitLog: function(logger) {
      let { title, content } = logger
      logger = { title, content }
      return _emit({ path, username, appname, uuid, labels, save })({ logger })
    }
  }
}

// 将 watcher.global 作为一个 config 收集器
watcher.global = GLOBAL_CONFIG

// Logger
watcher.logger = function(title, content) {
  if (!content) {
    content = title
  }
  title = title.toString()
  const { emitLog } = watcher()
  emitLog({ title, content })
}

watcher.use = function (watcherFunc) {
  if (typeof watcherFunc === 'function') {
    watcherFunc(watcher)
  } else {
    throw new Error('Given arg is not supported')
  }
}

module.exports = watcher<|endoftext|>


<commit_before>'use strict';

module.exports = function(options) {
  var useOptions = {
    guessName: function(name) {
      return '';
    }, mapping: {}
  };

  var cache = {};
  var target = {};
  var handler = {};

  var isObject = function(item) {
    return (null !== item) && ('object' === typeof item);
  };

  var setMapping = function(items) {
    if (false === isObject(items)) {
      return;
    }

    Object.keys(items).every(function(index) {
      let item = items[index];

      switch (typeof item) {
        case 'string':
          useOptions.mapping[index] = item;
          break;

        case 'object':
        case 'function':
          target[index] = item;
          break;

        default:
          break;
      }
    });
  };

  var setOptions = function(items) {
    if (false === isObject(items)) {
      return;
    }

    if (items.hasOwnProperty('guessName') && ('function' === typeof items.guessName)) {
      useOptions.guessName = items.guessName;
    }

    if (items.hasOwnProperty('mapping')) {
      setMapping(items.mapping);
    }
  };

  var packageName = function(name) {
    return name.trim().replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/[-\s]+/g, '-').toLowerCase();
  };

  var getNames = function(name) {
    let names = [name, packageName(name)];

    try {
      let guessName = useOptions.guessName(name);

      if (('string' === typeof guessName) && ('' !== guessName)) {
        names.push(guessName);
      }

      return names;
    } catch (error) {
      return names;
    }
  };

  var getFromMapping = function(target, property) {
    const items = useOptions.mapping;

    if (false === items.hasOwnProperty(property)) {
      return null;
    }

    try {
      target[property] = require(items[property]);
      return target[property];
    } catch (error) {
      return null;
    }
  };

  var getFromTarget = function(target, names) {
    let value = null;

    names.every(function(name) {
      if (target.hasOwnProperty(name)) {
        value = target[name];
        return false;
      }

      return true;
    });

    return value;
  };

  var getFromRequire = function(target, names) {
    let value = null;

    names.every(function(name) {
      try {
        target[name] = require(name);
        value = target[name];
        return false;
      } catch (error) {
        return true;
      }
    });

    return value;
  };

  handler.get = function(target, property, receiver) {
    if (cache.hasOwnProperty(property)) {
      return cache[property];
    }

    cache[property] = getFromMapping(target, property);

    if (null !== cache[property]) {
      return cache[property];
    }

    const names = getNames(property);
    cache[property] = getFromTarget(target, names);

    if (null !== cache[property]) {
      return cache[property];
    }

    cache[property] = getFromRequire(target, names);

    if (null !== cache[property]) {
      return cache[property];
    }

    delete cache[property];
    const error = new Error("Cannot find module '" + property + "'");
    error.code = 'MODULE_NOT_FOUND';
    throw error;
  };

  setOptions(options);
  return new Proxy(target, handler);
};

let $ = module.exports();
console.log($.noextist);
<commit_msg>remove cache<commit_after>'use strict';

module.exports = function(options) {
  var useOptions = {
    guessName: function(name) {
      return '';
    }, mapping: {}
  };

  var target = {};
  var handler = {};

  var isObject = function(item) {
    return (null !== item) && ('object' === typeof item);
  };

  var setMapping = function(items) {
    if (false === isObject(items)) {
      return;
    }

    Object.keys(items).every(function(index) {
      let item = items[index];

      switch (typeof item) {
        case 'string':
          useOptions.mapping[index] = item;
          break;

        case 'object':
        case 'function':
          target[index] = item;
          break;

        default:
          break;
      }
    });
  };

  var setOptions = function(items) {
    if (false === isObject(items)) {
      return;
    }

    if (items.hasOwnProperty('guessName') && ('function' === typeof items.guessName)) {
      useOptions.guessName = items.guessName;
    }

    if (items.hasOwnProperty('mapping')) {
      setMapping(items.mapping);
    }
  };

  var packageName = function(name) {
    return name.trim().replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/[-\s]+/g, '-').toLowerCase();
  };

  var getNames = function(name) {
    let names = [name, packageName(name)];

    try {
      let guessName = useOptions.guessName(name);

      if (('string' === typeof guessName) && ('' !== guessName)) {
        names.push(guessName);
      }

      return names;
    } catch (error) {
      return names;
    }
  };

  var getFromMapping = function(target, property) {
    const items = useOptions.mapping;

    if (false === items.hasOwnProperty(property)) {
      return null;
    }

    try {
      target[property] = require(items[property]);
      return target[property];
    } catch (error) {
      return null;
    }
  };

  var getFromRequire = function(target, names) {
    let value = null;

    names.every(function(name) {
      try {
        value = require(name);
        return false;
      } catch (error) {
        return true;
      }
    });

    return value;
  };

  handler.get = function(target, property, receiver) {
    if (target.hasOwnProperty(property)) {
      return target[property];
    }

    target[property] = getFromMapping(target, property);

    if (null !== target[property]) {
      return target[property];
    }

    const names = getNames(property);
    target[property] = getFromRequire(target, names);

    if (null !== target[property]) {
      return target[property];
    }

    delete target[property];
    const error = new Error("Cannot find module '" + property + "'");
    error.code = 'MODULE_NOT_FOUND';
    throw error;
  };

  setOptions(options);
  return new Proxy(target, handler);
};

let $ = module.exports();
console.log($.noextist);
<|endoftext|>


<commit_before>var net = require('net');
var protobuf = require('protocol-buffers')
const fs = require('fs')
var readline = require('readline')

var rl = readline.createInterface({
	input: process.stdin,
	output: process.stdout
});

var messages = protobuf(fs.readFileSync('protocol.proto'))

var HOST = '127.0.0.1';
var PORT = 4242;

var encodedBuffer = messages.BasRequestResponse.encode({
	request_type: messages.RequestResponseType.FC_SEND_TEXT_MESSAGE,
	text_message: 'hello world'
})

var client = new net.Socket();
client.connect(PORT, HOST, function() {

	console.log('CONNECTED TO: ' + HOST + ':' + PORT);
	// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
	client.write(encodedBuffer);

});

// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {

	var serverMessage = messages.BasRequestResponse.decode(data)
	console.log('Server Response: ' + serverMessage.request_type);
	// Close the client socket completely
	//client.destroy();
	if (serverMessage.request_type == messages.RequestResponseType.FS_ASK_NAME) {
		console.log('Please tell me your name:');
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_SEND_ALL_USERS_INFOS) {
		console.log("New Player  added to table");
		console.log("Cross Player : " + serverMessage.cross_user_name);
		console.log("Left Player  : " + serverMessage.left_user_name);
		console.log("Right Player : " + serverMessage.right_user_name);
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_SEND_PLAYER_CARDS) { // kartlari goster
		console.log("Your cards : " + serverMessage.user_cards.map(function(card) {
			return cardNumberToString(card.card_number) + " of " + cardTypeToString(card.card_type)
		}).join())
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_ASK_PLAY_COUNT) { //el sayisi sor
		console.log("Cross Play Count : " + serverMessage.cross_play_count)
		console.log("Left Play Count  : " + serverMessage.left_play_count)
		console.log("Right Play Count : " + serverMessage.right_play_count)
		console.log("How many plays?")
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_ASK_TRUMP) {
		console.log('Whats trump?')
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_SEND_WHOS_TURN){
		console.log("Cards on table " + serverMessage.cards_on_table.map(function(card){
			return cardNumberToString(card.card_number) + " of " + cardTypeToString(card.card_type)
		}).join())
		console.log("Whos Turn : " + userDirectionToString(serverMessage.user_direction))
	}
});

function userDirectionToString(userDirection) {
	switch(userDirection){
		case 0:
			return "Cross";
		case 1:
			return "Left";
		case 2:
			return "Right";
		case 3:
			return "Self";
	}
}
function cardNumberToString(cardNumber) {
	switch(cardNumber){
		case 0:
			return "Ace"
		case 1:
			return "Two"
		case 2:
			return "Three"
		case 3:
			return "Four"
		case 4:
			return "Five"
		case 5:
			return "Six"
		case 6:
			return "Seven"
		case 7:
			return "Eight"
		case 8:
			return "Nine"
		case 9:
			return "Ten"
		case 10:
			return "Jack"
		case 11:
			return "Queen"
		case 12:
			return "King"
	}
}

function cardTypeToString(cardType){
	switch(cardType){
		case 0:
			return "Spades"
		case 1:
			return "Hearts"
		case 2:
			return "Clubs"
		case 3:
			return "Diamonds"
	}
}

rl.on('line', function(line){
	var commands = line.trim().split(" ")
	switch (commands[0]){
		case "SN" :
		client.write(messages.BasRequestResponse.encode({
			request_type: messages.RequestResponseType.FC_SEND_NAME,
			name: commands[1]
		}));
		break;
		case "SPC":
		client.write(messages.BasRequestResponse.encode({
				request_type: messages.RequestResponseType.FC_SEND_PLAY_COUNT,
				play_count: parseInt(commands[1])
			}));
		break;
		case "WT":
		client.write(messages.BasRequestResponse.encode({
			request_type: messages.RequestResponseType.FC_SEND_TRUMP,
			card_in_play: {
				card_number: 1,
				card_type: messages.CardType.CT_SPADES
			}
		}));
		case "PC" :
		client.write(messages.BasRequestResponse.encode({
			request_type: messages.RequestResponseType.FC_PLAY_CARD,
			card_in_play: {
				card_number: commands[1],
				card_type: parseInt(commands[2])
			}
		}));
		break;
	}
})

// Add a 'close' event handler for the client socket
client.on('close', function() {
	console.log('Connection closed');
});

rl.on('close', function() {
  	console.log('Destroying app')
	process.stdin.destroy();
	client.end();
	client.destroy();
	process.exit(0);
});

process.on('SIGINT', function() {
	console.log('Destroying app')
	rl.close();
	process.stdin.destroy();
	client.end();
	client.destroy();
	process.exit(0);
});<commit_msg>play card command implemented<commit_after>var net = require('net');
var protobuf = require('protocol-buffers')
const fs = require('fs')
var readline = require('readline')

var rl = readline.createInterface({
	input: process.stdin,
	output: process.stdout
});

var messages = protobuf(fs.readFileSync('protocol.proto'))

var HOST = '127.0.0.1';
var PORT = 4242;

var encodedBuffer = messages.BasRequestResponse.encode({
	request_type: messages.RequestResponseType.FC_SEND_TEXT_MESSAGE,
	text_message: 'hello world'
})

var client = new net.Socket();
client.connect(PORT, HOST, function() {

	console.log('CONNECTED TO: ' + HOST + ':' + PORT);
	// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
	client.write(encodedBuffer);

});

// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {

	var serverMessage = messages.BasRequestResponse.decode(data)
	console.log('Server Response: ' + serverMessage.request_type);
	// Close the client socket completely
	//client.destroy();
	if (serverMessage.request_type == messages.RequestResponseType.FS_ASK_NAME) {
		console.log('Please tell me your name:');
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_SEND_ALL_USERS_INFOS) {
		console.log("New Player  added to table");
		console.log("Cross Player : " + serverMessage.cross_user_name);
		console.log("Left Player  : " + serverMessage.left_user_name);
		console.log("Right Player : " + serverMessage.right_user_name);
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_SEND_PLAYER_CARDS) { // kartlari goster
		console.log("Your cards : " + serverMessage.user_cards.map(function(card) {
			return cardNumberToString(card.card_number) + " of " + cardTypeToString(card.card_type)
		}).join())
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_ASK_PLAY_COUNT) { //el sayisi sor
		console.log("Cross Play Count : " + serverMessage.cross_play_count)
		console.log("Left Play Count  : " + serverMessage.left_play_count)
		console.log("Right Play Count : " + serverMessage.right_play_count)
		console.log("How many plays?")
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_ASK_TRUMP) {
		console.log('Whats trump?')
	} else if (serverMessage.request_type == messages.RequestResponseType.FS_SEND_WHOS_TURN){
		console.log("Cards on table " + serverMessage.cards_on_table.map(function(card){
			return cardNumberToString(card.card_number) + " of " + cardTypeToString(card.card_type)
		}).join())
		console.log("Your cards " + serverMessage.user_cards.map(function(card){
			return cardNumberToString(card.card_number) + " of " + cardTypeToString(card.card_type)
		}).join())
		console.log("Whos Turn : " + userDirectionToString(serverMessage.user_direction))
	}
});

function cardNumberToEnum(cardNumber){
	switch(cardNumber){
		case 0:
			return messages.CardNumber.CN_ACE;
		case 1:
			return messages.CardNumber.CN_TWO;
		case 2:
			return messages.CardNumber.CN_THREE;
		case 3:
			return messages.CardNumber.CN_FOUR;
		case 4:
			return messages.CardNumber.CN_FIVE;
		case 5:
			return messages.CardNumber.CN_SIX;
		case 6:
			return messages.CardNumber.CN_SEVEN;
		case 7:
			return messages.CardNumber.CN_EIGHT;
		case 8:
			return messages.CardNumber.CN_NINE;
		case 9:
			return messages.CardNumber.CN_TEN;
		case 10:
			return messages.CardNumber.CN_JACK;
		case 11:
			return messages.CardNumber.CN_QUEEN;
		case 12:
			return messages.CardNumber.CN_KING;
	}
}

function userDirectionToString(userDirection) {
	switch(userDirection){
		case 0:
			return "Cross";
		case 1:
			return "Left";
		case 2:
			return "Right";
		case 3:
			return "Self";
	}
}
function cardNumberToString(cardNumber) {
	switch(cardNumber){
		case 0:
			return "Ace"
		case 1:
			return "Two"
		case 2:
			return "Three"
		case 3:
			return "Four"
		case 4:
			return "Five"
		case 5:
			return "Six"
		case 6:
			return "Seven"
		case 7:
			return "Eight"
		case 8:
			return "Nine"
		case 9:
			return "Ten"
		case 10:
			return "Jack"
		case 11:
			return "Queen"
		case 12:
			return "King"
	}
}

function cardTypeToString(cardType){
	switch(cardType){
		case 0:
			return "Spades"
		case 1:
			return "Hearts"
		case 2:
			return "Clubs"
		case 3:
			return "Diamonds"
	}
}

function cardTypeToEnum(cardType){

	switch(cardType){
		case 0:
			return messages.CardType.CT_SPADES;
		case 1:
			return messages.CardType.CT_HEARTS;
		case 2:
			return messages.CardType.CT_CLUBS;
		case 3:
			return messages.CardType.CT_DIAMONDS;
	}
}

rl.on('line', function(line){
	var commands = line.trim().split(" ")
	switch (commands[0]){
		case "SN" :
		client.write(messages.BasRequestResponse.encode({
			request_type: messages.RequestResponseType.FC_SEND_NAME,
			name: commands[1]
		}));
		break;
		case "SPC":
		client.write(messages.BasRequestResponse.encode({
				request_type: messages.RequestResponseType.FC_SEND_PLAY_COUNT,
				play_count: parseInt(commands[1])
			}));
		break;
		case "WT":
		client.write(messages.BasRequestResponse.encode({
			request_type: messages.RequestResponseType.FC_SEND_TRUMP,
			card_in_play: {
				card_number: messages.CardNumber.CN_ACE,
				card_type: cardTypeToEnum(parseInt(commands[2]))
			}
		}));
		break;
		case "PC" :
		client.write(messages.BasRequestResponse.encode({
			request_type: messages.RequestResponseType.FC_PLAY_CARD,
			card_in_play: {
				card_number: cardNumberToEnum(parseInt(commands[1])),
				card_type: cardTypeToEnum(parseInt(commands[2]))
			}
		}));
		break;
	}
})

// Add a 'close' event handler for the client socket
client.on('close', function() {
	console.log('Connection closed');
});

rl.on('close', function() {
  	console.log('Destroying app')
	process.stdin.destroy();
	client.end();
	client.destroy();
	process.exit(0);
});

process.on('SIGINT', function() {
	console.log('Destroying app')
	rl.close();
	process.stdin.destroy();
	client.end();
	client.destroy();
	process.exit(0);
});<|endoftext|>


<commit_before>/*
 *
 * @format
 * @flow
 *
 */

import * as React from 'react';
import {
  View,
  StyleSheet,
  TouchableOpacity,
  BackHandler,
  NativeModules,
  Platform,
  PermissionsAndroid,
} from 'react-native';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';

import Overlay from './components/Overlay';
import Sheet from './components/Sheet';
import Button from './components/Button';

const ANDROID_KIT_KAT_SDK_VERSION = 19;
const androidPermissionRequestRequired = Platform.Version < ANDROID_KIT_KAT_SDK_VERSION;

const styles = StyleSheet.create({
  actionSheetContainer: {
    flex: 1,
    paddingTop: 10,
    paddingBottom: 0,
    justifyContent: 'flex-end',
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
  },
  buttonContainer: {
    overflow: 'hidden',
    backgroundColor: 'white',
    paddingBottom: 5,
    paddingTop: 5,
  },
});

type Props = {
  visible: boolean,
  onCancel: () => void,
  children: React.Node,
  style?: ViewStyleProp,
  overlayStyle?: ViewStyleProp,
};

const shareSheetStyle = { flex: 1 };

class ShareSheet extends React.Component<Props> {
  backButtonHandler: () => boolean;

  componentDidMount() {
    this.backButtonHandler = this.backButtonHandler.bind(this);
    BackHandler.addEventListener('backPress', this.backButtonHandler);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener('backPress', this.backButtonHandler);
  }

  backButtonHandler() {
    if (this.props.visible) {
      this.props.onCancel();
      return true;
    }
    return false;
  }
  render() {
    const { style = {}, overlayStyle = {}, ...props } = this.props;
    return (
      <Overlay visible={this.props.visible} {...props}>
        <View style={[styles.actionSheetContainer, overlayStyle]}>
          <TouchableOpacity style={shareSheetStyle} onPress={this.props.onCancel} />
          <Sheet visible={this.props.visible}>
            <View style={[styles.buttonContainer, style]}>{this.props.children}</View>
          </Sheet>
        </View>
      </Overlay>
    );
  }
}

type Options = {
  url?: string,
  urls?: Array<string>,
  filename?: string,
  filenames?: Array<string>,
  type?: string,
  message?: string,
  title?: string,
  subject?: string,
  recipient?: string,
  excludedActivityTypes?: string,
  failOnCancel?: boolean,
  showAppsToView?: boolean,
  saveToFiles?: boolean,
  appId: string,
};
type MultipleOptions = {
  url?: string,
  urls?: Array<string>,
  filename?: string,
  filenames?: Array<string>,
  type?: string,
  message?: string,
  title?: string,
  subject?: string,
  activityItemSources?: Array<ActivityItemSource>,
  excludedActivityTypes?: string,
  failOnCancel?: boolean,
  showAppsToView?: boolean,
  saveToFiles?: boolean,
};

type ActivityType =
  | 'addToReadingList'
  | 'airDrop'
  | 'assignToContact'
  | 'copyToPasteBoard'
  | 'mail'
  | 'message'
  | 'openInIBooks' // iOS 9 or later
  | 'postToFacebook'
  | 'postToFlickr'
  | 'postToTencentWeibo'
  | 'postToTwitter'
  | 'postToVimeo'
  | 'postToWeibo'
  | 'print'
  | 'saveToCameraRoll'
  | 'markupAsPDF'; // iOS 11 or later

type ActivityItem = { type: 'text' | 'url', content: string };

type LinkMetadata = {
  originalUrl?: string,
  url?: string,
  title?: string,
  icon?: string,
  image?: string,
  remoteVideoUrl?: string,
  video?: string,
};

type ActivityItemSource = {
  placeholderItem: ActivityItem,
  item: { [ActivityType | string]: ?ActivityItem },
  subject?: { [ActivityType | string]: string },
  dataTypeIdentifier?: { [ActivityType | string]: string },
  thumbnailImage?: { [ActivityType | string]: string },
  linkMetadata?: LinkMetadata,
};

type OpenReturn = { app?: string, dismissedAction?: boolean };
type ShareSingleReturn = { message: string, isInstalled?: boolean };

const requireAndAskPermissions = async (options: Options | MultipleOptions): Promise<any> => {
  if ((options.url || options.urls) && Platform.OS === 'android') {
    const urls: Array<string> = options.urls || (options.url ? [options.url] : []);
    try {
      const resultArr = await Promise.all(
        urls.map(
          (url) =>
            new Promise((res, rej) => {
              NativeModules.RNShare.isBase64File(
                url,
                (e) => {
                  rej(e);
                },
                (isBase64) => {
                  res(isBase64);
                },
              );
            }),
        ),
      );

      const requirePermission = resultArr.includes(true);
      if (!requirePermission) {
        return Promise.resolve(true);
      }
      const hasPermission = await PermissionsAndroid.check(
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
      );
      if (hasPermission) {
        return Promise.resolve(true);
      }

      if (androidPermissionRequestRequired) {
        const result = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
        );
        if (result === PermissionsAndroid.RESULTS.GRANTED) {
          return Promise.resolve();
        }
        throw new Error('Write Permission not available');
      }
    } catch (e) {
      return Promise.reject(e);
    }
  }
  return Promise.resolve(true);
};

class RNShare {
  static Button: any;
  static ShareSheet: RNShare.ShareSheet;
  static Overlay: any;
  static Sheet: any;
  static Social = {
    FACEBOOK: NativeModules.RNShare.FACEBOOK || 'facebook',
    FACEBOOK_STORIES: NativeModules.RNShare.FACEBOOK_STORIES || 'facebook-stories',
    PAGESMANAGER: NativeModules.RNShare.PAGESMANAGER || 'pagesmanager',
    TWITTER: NativeModules.RNShare.TWITTER || 'twitter',
    WHATSAPP: NativeModules.RNShare.WHATSAPP || 'whatsapp',
    INSTAGRAM: NativeModules.RNShare.INSTAGRAM || 'instagram',
    INSTAGRAM_STORIES: NativeModules.RNShare.INSTAGRAM_STORIES || 'instagramstories',
    GOOGLEPLUS: NativeModules.RNShare.GOOGLEPLUS || 'googleplus',
    EMAIL: NativeModules.RNShare.EMAIL || 'email',
    PINTEREST: NativeModules.RNShare.PINTEREST || 'pinterest',
    LINKEDIN: NativeModules.RNShare.LINKEDIN || 'linkedin',
    SMS: NativeModules.RNShare.SMS || 'sms',
  };

  static InstagramStories = {
    SHARE_BACKGROUND_IMAGE: NativeModules.RNShare.SHARE_BACKGROUND_IMAGE || 'shareBackgroundImage',
    SHARE_BACKGROUND_VIDEO: NativeModules.RNShare.SHARE_BACKGROUND_VIDEO || 'shareBackgroundVideo',
    SHARE_STICKER_IMAGE: NativeModules.RNShare.SHARE_STICKER_IMAGE || 'shareStickerImage',
    SHARE_BACKGROUND_AND_STICKER_IMAGE:
      NativeModules.RNShare.SHARE_BACKGROUND_AND_STICKER_IMAGE || 'shareBackgroundAndStickerImage',
  };

  static FacebookStories = {
    SHARE_BACKGROUND_IMAGE: NativeModules.RNShare.SHARE_BACKGROUND_IMAGE || 'shareBackgroundImage',
    SHARE_STICKER_IMAGE: NativeModules.RNShare.SHARE_STICKER_IMAGE || 'shareStickerImage',
    SHARE_BACKGROUND_AND_STICKER_IMAGE:
      NativeModules.RNShare.SHARE_BACKGROUND_AND_STICKER_IMAGE || 'shareBackgroundAndStickerImage',
  };

  static open(options: Options | MultipleOptions): Promise<OpenReturn> {
    return new Promise((resolve, reject) => {
      requireAndAskPermissions(options)
        .then(() => {
          if (Platform.OS === 'ios' && options.url && !options.urls) {
            // Backward compatibility with { Share } from react-native
            const url = options.url;
            delete options.url;

            options.urls = [url];

            if (options.filename && !options.filenames) {
              options.filenames = [options.filename];
              delete options.filename;
            }
          }

          NativeModules.RNShare.open(
            options,
            (e) => {
              return reject({ error: e });
            },
            (success, activityType) => {
              if (success) {
                return resolve({
                  app: activityType,
                  message: activityType,
                });
              } else if (options.failOnCancel === false) {
                return resolve({
                  dismissedAction: true,
                });
              } else {
                reject(new Error('User did not share'));
              }
            },
          );
        })
        .catch((e) => reject(e));
    });
  }

  static shareSingle(options: Options): Promise<ShareSingleReturn> {
    if (Platform.OS === 'ios' || Platform.OS === 'android') {
      return new Promise((resolve, reject) => {
        requireAndAskPermissions(options)
          .then(() => {
            NativeModules.RNShare.shareSingle(
              options,
              (e) => {
                return reject({ error: e });
              },
              (e, activityType) => {
                return resolve({
                  message: e,
                  app: activityType,
                });
              },
            );
          })
          .catch((e) => reject(e));
      });
    } else {
      throw new Error('Not implemented');
    }
  }

  static isPackageInstalled(packageName: string): Promise<ShareSingleReturn> {
    if (Platform.OS === 'android') {
      return new Promise((resolve, reject) => {
        NativeModules.RNShare.isPackageInstalled(
          packageName,
          (e) => {
            return reject({ error: e });
          },
          (isInstalled) => {
            return resolve({
              isInstalled: isInstalled,
              message: 'Package is Installed',
            });
          },
        );
      });
    } else {
      throw new Error('Not implemented');
    }
  }
}

export { Overlay, Sheet, Button, ShareSheet };
export default RNShare;
<commit_msg>fix: Flowtype error (#887)<commit_after>/*
 *
 * @format
 * @flow
 *
 */

import * as React from 'react';
import {
  View,
  StyleSheet,
  TouchableOpacity,
  BackHandler,
  NativeModules,
  Platform,
  PermissionsAndroid,
} from 'react-native';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';

import Overlay from './components/Overlay';
import Sheet from './components/Sheet';
import Button from './components/Button';

const ANDROID_KIT_KAT_SDK_VERSION = 19;
const androidPermissionRequestRequired =
  parseInt(Platform.Version, 10) < ANDROID_KIT_KAT_SDK_VERSION;

const styles = StyleSheet.create({
  actionSheetContainer: {
    flex: 1,
    paddingTop: 10,
    paddingBottom: 0,
    justifyContent: 'flex-end',
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
  },
  buttonContainer: {
    overflow: 'hidden',
    backgroundColor: 'white',
    paddingBottom: 5,
    paddingTop: 5,
  },
});

type Props = {
  visible: boolean,
  onCancel: () => void,
  children: React.Node,
  style?: ViewStyleProp,
  overlayStyle?: ViewStyleProp,
};

const shareSheetStyle = { flex: 1 };

class ShareSheet extends React.Component<Props> {
  backButtonHandler: () => boolean;

  componentDidMount() {
    this.backButtonHandler = this.backButtonHandler.bind(this);
    BackHandler.addEventListener('backPress', this.backButtonHandler);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener('backPress', this.backButtonHandler);
  }

  backButtonHandler() {
    if (this.props.visible) {
      this.props.onCancel();
      return true;
    }
    return false;
  }
  render() {
    const { style = {}, overlayStyle = {}, ...props } = this.props;
    return (
      <Overlay visible={this.props.visible} {...props}>
        <View style={[styles.actionSheetContainer, overlayStyle]}>
          <TouchableOpacity style={shareSheetStyle} onPress={this.props.onCancel} />
          <Sheet visible={this.props.visible}>
            <View style={[styles.buttonContainer, style]}>{this.props.children}</View>
          </Sheet>
        </View>
      </Overlay>
    );
  }
}

type Options = {
  url?: string,
  urls?: Array<string>,
  filename?: string,
  filenames?: Array<string>,
  type?: string,
  message?: string,
  title?: string,
  subject?: string,
  recipient?: string,
  excludedActivityTypes?: string,
  failOnCancel?: boolean,
  showAppsToView?: boolean,
  saveToFiles?: boolean,
  appId: string,
};
type MultipleOptions = {
  url?: string,
  urls?: Array<string>,
  filename?: string,
  filenames?: Array<string>,
  type?: string,
  message?: string,
  title?: string,
  subject?: string,
  activityItemSources?: Array<ActivityItemSource>,
  excludedActivityTypes?: string,
  failOnCancel?: boolean,
  showAppsToView?: boolean,
  saveToFiles?: boolean,
};

type ActivityType =
  | 'addToReadingList'
  | 'airDrop'
  | 'assignToContact'
  | 'copyToPasteBoard'
  | 'mail'
  | 'message'
  | 'openInIBooks' // iOS 9 or later
  | 'postToFacebook'
  | 'postToFlickr'
  | 'postToTencentWeibo'
  | 'postToTwitter'
  | 'postToVimeo'
  | 'postToWeibo'
  | 'print'
  | 'saveToCameraRoll'
  | 'markupAsPDF'; // iOS 11 or later

type ActivityItem = { type: 'text' | 'url', content: string };

type LinkMetadata = {
  originalUrl?: string,
  url?: string,
  title?: string,
  icon?: string,
  image?: string,
  remoteVideoUrl?: string,
  video?: string,
};

type ActivityItemSource = {
  placeholderItem: ActivityItem,
  item: { [ActivityType | string]: ?ActivityItem },
  subject?: { [ActivityType | string]: string },
  dataTypeIdentifier?: { [ActivityType | string]: string },
  thumbnailImage?: { [ActivityType | string]: string },
  linkMetadata?: LinkMetadata,
};

type OpenReturn = { app?: string, dismissedAction?: boolean };
type ShareSingleReturn = { message: string, isInstalled?: boolean };

const requireAndAskPermissions = async (options: Options | MultipleOptions): Promise<any> => {
  if ((options.url || options.urls) && Platform.OS === 'android') {
    const urls: Array<string> = options.urls || (options.url ? [options.url] : []);
    try {
      const resultArr = await Promise.all(
        urls.map(
          (url) =>
            new Promise((res, rej) => {
              NativeModules.RNShare.isBase64File(
                url,
                (e) => {
                  rej(e);
                },
                (isBase64) => {
                  res(isBase64);
                },
              );
            }),
        ),
      );

      const requirePermission = resultArr.includes(true);
      if (!requirePermission) {
        return Promise.resolve(true);
      }
      const hasPermission = await PermissionsAndroid.check(
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
      );
      if (hasPermission) {
        return Promise.resolve(true);
      }

      if (androidPermissionRequestRequired) {
        const result = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
        );
        if (result === PermissionsAndroid.RESULTS.GRANTED) {
          return Promise.resolve();
        }
        throw new Error('Write Permission not available');
      }
    } catch (e) {
      return Promise.reject(e);
    }
  }
  return Promise.resolve(true);
};

class RNShare {
  static Button: any;
  static ShareSheet: RNShare.ShareSheet;
  static Overlay: any;
  static Sheet: any;
  static Social = {
    FACEBOOK: NativeModules.RNShare.FACEBOOK || 'facebook',
    FACEBOOK_STORIES: NativeModules.RNShare.FACEBOOK_STORIES || 'facebook-stories',
    PAGESMANAGER: NativeModules.RNShare.PAGESMANAGER || 'pagesmanager',
    TWITTER: NativeModules.RNShare.TWITTER || 'twitter',
    WHATSAPP: NativeModules.RNShare.WHATSAPP || 'whatsapp',
    INSTAGRAM: NativeModules.RNShare.INSTAGRAM || 'instagram',
    INSTAGRAM_STORIES: NativeModules.RNShare.INSTAGRAM_STORIES || 'instagramstories',
    GOOGLEPLUS: NativeModules.RNShare.GOOGLEPLUS || 'googleplus',
    EMAIL: NativeModules.RNShare.EMAIL || 'email',
    PINTEREST: NativeModules.RNShare.PINTEREST || 'pinterest',
    LINKEDIN: NativeModules.RNShare.LINKEDIN || 'linkedin',
    SMS: NativeModules.RNShare.SMS || 'sms',
  };

  static InstagramStories = {
    SHARE_BACKGROUND_IMAGE: NativeModules.RNShare.SHARE_BACKGROUND_IMAGE || 'shareBackgroundImage',
    SHARE_BACKGROUND_VIDEO: NativeModules.RNShare.SHARE_BACKGROUND_VIDEO || 'shareBackgroundVideo',
    SHARE_STICKER_IMAGE: NativeModules.RNShare.SHARE_STICKER_IMAGE || 'shareStickerImage',
    SHARE_BACKGROUND_AND_STICKER_IMAGE:
      NativeModules.RNShare.SHARE_BACKGROUND_AND_STICKER_IMAGE || 'shareBackgroundAndStickerImage',
  };

  static FacebookStories = {
    SHARE_BACKGROUND_IMAGE: NativeModules.RNShare.SHARE_BACKGROUND_IMAGE || 'shareBackgroundImage',
    SHARE_STICKER_IMAGE: NativeModules.RNShare.SHARE_STICKER_IMAGE || 'shareStickerImage',
    SHARE_BACKGROUND_AND_STICKER_IMAGE:
      NativeModules.RNShare.SHARE_BACKGROUND_AND_STICKER_IMAGE || 'shareBackgroundAndStickerImage',
  };

  static open(options: Options | MultipleOptions): Promise<OpenReturn> {
    return new Promise((resolve, reject) => {
      requireAndAskPermissions(options)
        .then(() => {
          if (Platform.OS === 'ios' && options.url && !options.urls) {
            // Backward compatibility with { Share } from react-native
            const url = options.url;
            delete options.url;

            options.urls = [url];

            if (options.filename && !options.filenames) {
              options.filenames = [options.filename];
              delete options.filename;
            }
          }

          NativeModules.RNShare.open(
            options,
            (e) => {
              return reject({ error: e });
            },
            (success, activityType) => {
              if (success) {
                return resolve({
                  app: activityType,
                  message: activityType,
                });
              } else if (options.failOnCancel === false) {
                return resolve({
                  dismissedAction: true,
                });
              } else {
                reject(new Error('User did not share'));
              }
            },
          );
        })
        .catch((e) => reject(e));
    });
  }

  static shareSingle(options: Options): Promise<ShareSingleReturn> {
    if (Platform.OS === 'ios' || Platform.OS === 'android') {
      return new Promise((resolve, reject) => {
        requireAndAskPermissions(options)
          .then(() => {
            NativeModules.RNShare.shareSingle(
              options,
              (e) => {
                return reject({ error: e });
              },
              (e, activityType) => {
                return resolve({
                  message: e,
                  app: activityType,
                });
              },
            );
          })
          .catch((e) => reject(e));
      });
    } else {
      throw new Error('Not implemented');
    }
  }

  static isPackageInstalled(packageName: string): Promise<ShareSingleReturn> {
    if (Platform.OS === 'android') {
      return new Promise((resolve, reject) => {
        NativeModules.RNShare.isPackageInstalled(
          packageName,
          (e) => {
            return reject({ error: e });
          },
          (isInstalled) => {
            return resolve({
              isInstalled: isInstalled,
              message: 'Package is Installed',
            });
          },
        );
      });
    } else {
      throw new Error('Not implemented');
    }
  }
}

export { Overlay, Sheet, Button, ShareSheet };
export default RNShare;
<|endoftext|>