<commit_before>'use strict'

const ProgressBar = require('progress')
const table = require('table').table
const getBorderCharacters = require('table').getBorderCharacters
const Chalk = require('chalk')
const testColorSupport = require('color-support')
const prettyBytes = require('pretty-bytes')
const format = require('./format')
const percentiles = require('hdr-histogram-percentiles-obj').percentiles
const defaults = {
  // use stderr as its progressBar's default
  outputStream: process.stderr,
  renderProgressBar: true,
  renderResultsTable: true,
  renderLatencyTable: false
}

function track (instance, opts) {
  if (!instance) {
    throw new Error('instance required for tracking')
  }

  opts = Object.assign({}, defaults, opts)

  const chalk = new Chalk.constructor({ enabled: testColorSupport({ stream: opts.outputStream }) })
  // this default needs to be set after chalk is setup, because chalk is now local to this func
  opts.progressBarString = opts.progressBarString || `${chalk.green('running')} [:bar] :percent`

  const iOpts = instance.opts
  let durationProgressBar
  let amountProgressBar

  instance.on('start', () => {
    if (opts.renderProgressBar) {
      const socketPath = iOpts.socketPath ? ` (${iOpts.socketPath})` : ''
      let msg = `${iOpts.connections} connections`

      if (iOpts.pipelining > 1) {
        msg += ` with ${iOpts.pipelining} pipelining factor`
      }

      if (!iOpts.amount) {
        logToStream(`Running ${iOpts.duration}s test @ ${iOpts.url}${socketPath}\n${msg}\n`)

        durationProgressBar = trackDuration(instance, opts, iOpts)
      } else {
        logToStream(`Running ${iOpts.amount} requests test @ ${iOpts.url}${socketPath}\n${msg}\n`)

        amountProgressBar = trackAmount(instance, opts, iOpts)
      }
    }
  })

  // add listeners for progress bar to instance here so they aren't
  // added on restarting, causing listener leaks
  // note: Attempted to curry the functions below, but that breaks the functionality
  // as they use the scope/closure of the progress bar variables to allow them to be reset
  if (opts.renderProgressBar && opts.outputStream.isTTY) {
    if (!iOpts.amount) { // duration progress bar
      instance.on('tick', () => { durationProgressBar.tick() })
      instance.on('done', () => { durationProgressBar.tick(iOpts.duration - 1) })
      process.once('SIGINT', () => { durationProgressBar.tick(iOpts.duration - 1) })
    } else { // amount progress bar
      instance.on('response', () => { amountProgressBar.tick() })
      instance.on('reqError', () => { amountProgressBar.tick() })
      instance.on('done', () => { amountProgressBar.tick(iOpts.amount - 1) })
      process.once('SIGINT', () => { amountProgressBar.tick(iOpts.amount - 1) })
    }
  }

  instance.on('done', (result) => {
    // the code below this `if` just renders the results table...
    // if the user doesn't want to render the table, we can just return early
    if (!opts.renderResultsTable) return

    const tableOpts = {
      border: getBorderCharacters('void'),
      columnDefault: {
        paddingLeft: 0,
        paddingRight: 1
      },
      drawHorizontalLine: () => false
    }

    logToStream(table([
      asColor(chalk.cyan, ['Stat', '2.5%', '50%', '97.5%', '99%', 'Avg', 'Stdev', 'Max']),
      asLowRow(chalk.bold('Latency'), asMs(result.latency))
    ], tableOpts))
    logToStream(table([
      asColor(chalk.cyan, ['Stat', '1%', '2.5%', '50%', '97.5%', 'Avg', 'Stdev', 'Min']),
      asHighRow(chalk.bold('Req/Sec'), result.requests),
      asHighRow(chalk.bold('Bytes/Sec'), asBytes(result.throughput))
    ], tableOpts))
    logToStream('Req/Bytes counts sampled once per second.\n')

    if (opts.renderLatencyTable) {
      const latency = table([
        asColor(chalk.cyan, ['Percentile', 'Latency (ms)'])
      ].concat(percentiles.map((perc) => {
        const key = `p${perc}`.replace('.', '_')
        return [
          chalk.bold('' + perc),
          result.latency[key]
        ]
      })), {
        border: getBorderCharacters('void'),
        columnDefault: {
          paddingLeft: 0,
          paddingRight: 6
        },
        drawHorizontalLine: () => false
      })

      logToStream(latency)
    }

    if (result.non2xx) {
      logToStream(`${result['2xx']} 2xx responses, ${result.non2xx} non 2xx responses`)
    }
    logToStream(`${format(result.requests.total)} requests in ${result.duration}s, ${prettyBytes(result.throughput.total)} read`)
    if (result.errors) {
      logToStream(`${format(result.errors)} errors (${format(result.timeouts)} timeouts)`)
    }
  })

  function logToStream (msg) {
    opts.outputStream.write(msg + '\n')
  }
}

function trackDuration (instance, opts, iOpts) {
  // if switch needed needed to avoid
  // https://github.com/mcollina/autocannon/issues/60
  if (!opts.outputStream.isTTY) return

  const progressBar = new ProgressBar(opts.progressBarString, {
    width: 20,
    incomplete: ' ',
    total: iOpts.duration,
    clear: true,
    stream: opts.outputStream
  })

  progressBar.tick(0)
  return progressBar
}

function trackAmount (instance, opts, iOpts) {
  // if switch needed needed to avoid
  // https://github.com/mcollina/autocannon/issues/60
  if (!opts.outputStream.isTTY) return

  const progressBar = new ProgressBar(opts.progressBarString, {
    width: 20,
    incomplete: ' ',
    total: iOpts.amount,
    clear: true,
    stream: opts.outputStream
  })

  progressBar.tick(0)
  return progressBar
}

// create a table row for stats where low values is better
function asLowRow (name, stat) {
  return [
    name,
    stat.p2_5,
    stat.p50,
    stat.p97_5,
    stat.p99,
    stat.average,
    stat.stddev,
    typeof stat.max === 'string' ? stat.max : Math.floor(stat.max * 100) / 100
  ]
}

// create a table row for stats where high values is better
function asHighRow (name, stat) {
  return [
    name,
    stat.p1,
    stat.p2_5,
    stat.p50,
    stat.p97_5,
    stat.average,
    stat.stddev,
    typeof stat.min === 'string' ? stat.min : Math.floor(stat.min * 100) / 100
  ]
}

function asColor (colorise, row) {
  return row.map((entry) => colorise(entry))
}

function asMs (stat) {
  const result = Object.create(null)
  Object.keys(stat).forEach((k) => {
    result[k] = `${stat[k]} ms`
  })
  result.max = typeof stat.max === 'string' ? stat.max : `${Math.floor(stat.max * 100) / 100} ms`

  return result
}

function asBytes (stat) {
  const result = Object.create(stat)

  percentiles.forEach((p) => {
    const key = `p${p}`.replace('.', '_')
    result[key] = prettyBytes(stat[key])
  })

  result.average = prettyBytes(stat.average)
  result.stddev = prettyBytes(stat.stddev)
  result.max = prettyBytes(stat.max)
  result.min = prettyBytes(stat.min)
  return result
}

module.exports = track
<commit_msg>Initialize things only after start is emitted (#178)<commit_after>'use strict'

const ProgressBar = require('progress')
const table = require('table').table
const getBorderCharacters = require('table').getBorderCharacters
const Chalk = require('chalk')
const testColorSupport = require('color-support')
const prettyBytes = require('pretty-bytes')
const format = require('./format')
const percentiles = require('hdr-histogram-percentiles-obj').percentiles
const defaults = {
  // use stderr as its progressBar's default
  outputStream: process.stderr,
  renderProgressBar: true,
  renderResultsTable: true,
  renderLatencyTable: false
}

function track (instance, opts) {
  if (!instance) {
    throw new Error('instance required for tracking')
  }

  opts = Object.assign({}, defaults, opts)

  const chalk = new Chalk.constructor({ enabled: testColorSupport({ stream: opts.outputStream }) })
  // this default needs to be set after chalk is setup, because chalk is now local to this func
  opts.progressBarString = opts.progressBarString || `${chalk.green('running')} [:bar] :percent`

  const iOpts = instance.opts
  let durationProgressBar
  let amountProgressBar
  let addedListeners = false

  instance.on('start', () => {
    if (opts.renderProgressBar) {
      const socketPath = iOpts.socketPath ? ` (${iOpts.socketPath})` : ''
      let msg = `${iOpts.connections} connections`

      if (iOpts.pipelining > 1) {
        msg += ` with ${iOpts.pipelining} pipelining factor`
      }

      if (!iOpts.amount) {
        logToStream(`Running ${iOpts.duration}s test @ ${iOpts.url}${socketPath}\n${msg}\n`)

        durationProgressBar = trackDuration(instance, opts, iOpts)
      } else {
        logToStream(`Running ${iOpts.amount} requests test @ ${iOpts.url}${socketPath}\n${msg}\n`)

        amountProgressBar = trackAmount(instance, opts, iOpts)
      }

      addListener()
    }
  })

  function addListener () {
    // add listeners for progress bar to instance here so they aren't
    // added on restarting, causing listener leaks
    if (addedListeners) {
      return
    }

    addedListeners = true

    // note: Attempted to curry the functions below, but that breaks the functionality
    // as they use the scope/closure of the progress bar variables to allow them to be reset
    if (opts.outputStream.isTTY) {
      if (!iOpts.amount) { // duration progress bar
        instance.on('tick', () => { durationProgressBar.tick() })
        instance.on('done', () => { durationProgressBar.tick(iOpts.duration - 1) })
        process.once('SIGINT', () => { durationProgressBar.tick(iOpts.duration - 1) })
      } else { // amount progress bar
        instance.on('response', () => { amountProgressBar.tick() })
        instance.on('reqError', () => { amountProgressBar.tick() })
        instance.on('done', () => { amountProgressBar.tick(iOpts.amount - 1) })
        process.once('SIGINT', () => { amountProgressBar.tick(iOpts.amount - 1) })
      }
    }
  }

  instance.on('done', (result) => {
    // the code below this `if` just renders the results table...
    // if the user doesn't want to render the table, we can just return early
    if (!opts.renderResultsTable) return

    const tableOpts = {
      border: getBorderCharacters('void'),
      columnDefault: {
        paddingLeft: 0,
        paddingRight: 1
      },
      drawHorizontalLine: () => false
    }

    logToStream(table([
      asColor(chalk.cyan, ['Stat', '2.5%', '50%', '97.5%', '99%', 'Avg', 'Stdev', 'Max']),
      asLowRow(chalk.bold('Latency'), asMs(result.latency))
    ], tableOpts))
    logToStream(table([
      asColor(chalk.cyan, ['Stat', '1%', '2.5%', '50%', '97.5%', 'Avg', 'Stdev', 'Min']),
      asHighRow(chalk.bold('Req/Sec'), result.requests),
      asHighRow(chalk.bold('Bytes/Sec'), asBytes(result.throughput))
    ], tableOpts))
    logToStream('Req/Bytes counts sampled once per second.\n')

    if (opts.renderLatencyTable) {
      const latency = table([
        asColor(chalk.cyan, ['Percentile', 'Latency (ms)'])
      ].concat(percentiles.map((perc) => {
        const key = `p${perc}`.replace('.', '_')
        return [
          chalk.bold('' + perc),
          result.latency[key]
        ]
      })), {
        border: getBorderCharacters('void'),
        columnDefault: {
          paddingLeft: 0,
          paddingRight: 6
        },
        drawHorizontalLine: () => false
      })

      logToStream(latency)
    }

    if (result.non2xx) {
      logToStream(`${result['2xx']} 2xx responses, ${result.non2xx} non 2xx responses`)
    }
    logToStream(`${format(result.requests.total)} requests in ${result.duration}s, ${prettyBytes(result.throughput.total)} read`)
    if (result.errors) {
      logToStream(`${format(result.errors)} errors (${format(result.timeouts)} timeouts)`)
    }
  })

  function logToStream (msg) {
    opts.outputStream.write(msg + '\n')
  }
}

function trackDuration (instance, opts, iOpts) {
  // if switch needed needed to avoid
  // https://github.com/mcollina/autocannon/issues/60
  if (!opts.outputStream.isTTY) return

  const progressBar = new ProgressBar(opts.progressBarString, {
    width: 20,
    incomplete: ' ',
    total: iOpts.duration,
    clear: true,
    stream: opts.outputStream
  })

  progressBar.tick(0)
  return progressBar
}

function trackAmount (instance, opts, iOpts) {
  // if switch needed needed to avoid
  // https://github.com/mcollina/autocannon/issues/60
  if (!opts.outputStream.isTTY) return

  const progressBar = new ProgressBar(opts.progressBarString, {
    width: 20,
    incomplete: ' ',
    total: iOpts.amount,
    clear: true,
    stream: opts.outputStream
  })

  progressBar.tick(0)
  return progressBar
}

// create a table row for stats where low values is better
function asLowRow (name, stat) {
  return [
    name,
    stat.p2_5,
    stat.p50,
    stat.p97_5,
    stat.p99,
    stat.average,
    stat.stddev,
    typeof stat.max === 'string' ? stat.max : Math.floor(stat.max * 100) / 100
  ]
}

// create a table row for stats where high values is better
function asHighRow (name, stat) {
  return [
    name,
    stat.p1,
    stat.p2_5,
    stat.p50,
    stat.p97_5,
    stat.average,
    stat.stddev,
    typeof stat.min === 'string' ? stat.min : Math.floor(stat.min * 100) / 100
  ]
}

function asColor (colorise, row) {
  return row.map((entry) => colorise(entry))
}

function asMs (stat) {
  const result = Object.create(null)
  Object.keys(stat).forEach((k) => {
    result[k] = `${stat[k]} ms`
  })
  result.max = typeof stat.max === 'string' ? stat.max : `${Math.floor(stat.max * 100) / 100} ms`

  return result
}

function asBytes (stat) {
  const result = Object.create(stat)

  percentiles.forEach((p) => {
    const key = `p${p}`.replace('.', '_')
    result[key] = prettyBytes(stat[key])
  })

  result.average = prettyBytes(stat.average)
  result.stddev = prettyBytes(stat.stddev)
  result.max = prettyBytes(stat.max)
  result.min = prettyBytes(stat.min)
  return result
}

module.exports = track
<|endoftext|>


<commit_before>module.exports = [
  'installation',
  'getting-started',
  'basics',
  {
    type: 'category',
    label: 'Main Concepts',
    items: [
      'hosts',
      'tasks',
    ],
  },
  'ci-cd',
  'yaml',
  'cli',
  {
    type: 'category',
    label: 'Advanced Guides',
    items: [
      'avoid-php-fpm-reloading',
    ],
  },
  'api',
  {
    type: 'category',
    label: 'Other',
    items: [
      'UPGRADE',
    ],
  },
]
<commit_msg>Update sidebar.js<commit_after>module.exports = [
  'installation',
  'getting-started',
  'basics',
  {
    type: 'category',
    label: 'Main Concepts',
    items: [
      'hosts',
      'tasks',
    ],
  },
  'ci-cd',
  'yaml',
  'cli',
  'api',
  {
    type: 'category',
    label: 'Other',
    items: [
      'avoid-php-fpm-reloading',
      'UPGRADE',
      'KNOWN_BUGS',
    ],
  },
]
<|endoftext|>


<commit_before>import React, { Component, Fragment } from 'react';
import CountUp from 'react-countup';
import { description, repository } from 'react-countup/package';
import { RotateCw } from 'react-feather';
import GithubCorner from 'react-github-corner';
import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live';
import styled from 'styled-components';

const RefreshButton = styled.button`
  background: none;
  border: none;
  color: slategray;
  opacity: 0.5;
  outline: none;
  padding: 0;
  position: absolute;
  right: 16px;
  top: 16px;
  transition: 0.2s;
  width: 16px;

  &:hover {
    opacity: 1;
  }
`;

const Editor = styled(LiveEditor).attrs({ style: { padding: 16 } })`
  font-family: 'Overpass Mono', monospace;
  overflow: auto;
`;

const Error = styled(LiveError)`
  background: tomato;
  color: white;
  grid-column: span 2;
  padding: 16px;
`;

class Example extends Component {
  refresh = () => this.forceUpdate();

  render() {
    const { children, code, title, ...rest } = this.props;

    return (
      <Fragment>
        <Fragment>
          <Subtitle>{title}</Subtitle>
          <Provider scope={{ CountUp }} code={code.trim()} {...rest}>
            <Editor />
            <RefreshButton onClick={this.refresh} title="Re-render">
              <RotateCw size={16} />
            </RefreshButton>
            <Preview />
            <Error />
          </Provider>
          {children}
        </Fragment>
      </Fragment>
    );
  }
}

const Main = styled.main`
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
    sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
  margin: 32px auto;
  max-width: 960px;
`;

const Preview = styled(LivePreview)`
  align-items: center;
  background: whitesmoke;
  display: flex;
  justify-content: center;
  min-height: 64px;
  padding: 16px;

  & div {
    align-items: center;
    display: flex;
    flex-direction: column;
  }

  & span {
    display: flex;
    justify-content: center;
  }

  & button {
    background: white;
    border: none;
    border-radius: 4px;
    box-shadow: 0 4px 8px gainsboro;
    display: block;
    font-family: inherit;
    font-size: inherit;
    margin: 16px 0 auto;
    outline: none;
    padding: 8px 32px;

    &:active {
      transform: translateY(2px);
    }

    &:hover {
      background: snow;
    }
  }
`;

const Provider = styled(LiveProvider)`
  border-radius: 8px;
  box-shadow: 0 4px 8px gainsboro;
  overflow: hidden;
  display: grid;
  grid-template-columns: repeat(2, 50%);
  position: relative;
`;

const Subtitle = styled.h2`
  margin-top: 2em;
`;
const Text = styled.p``;
const Title = styled.h1``;

const simple = `
<CountUp end={123456} />
`;

const renderProp = `
<CountUp
  className="account-balance"
  start={-875.039}
  end={160527.012}
  duration={2.75}
  separator=" "
  decimals={4}
  decimal=","
  prefix="EUR "
  suffix=" left"
  onEnd={() => console.log('Ended! 👏')}
  onStart={() => console.log('Started! 💨')}
  >
  {({ countUpRef, start }) => (

      <button onClick={start}>Start</button>

  )}
</CountUp>
`;

const autoStart = `
<CountUp start={0} end={100} delay={0}>
  {({ countUpRef, start }) => (

      <button onClick={start}>Start</button>

  )}
</CountUp>
`;

const delayStart = `
<CountUp delay={2} end={100} />
`;

const repo = `https://github.com/${repository}`;

const App = () => (

    <Title>React CountUp</Title>
    <Text>{description}</Text>
    <Text>
      <a href={`${repo}#installation`}>Installation
      {' · '}
      <a href={`${repo}#installation`}>API
    </Text>
    <Example code={simple} title="Simple">
      <Text>Edit the code to see live changes.</Text>
    </Example>
    <Example code={renderProp} title="Render prop" />
    <Example code={autoStart} title="Autostart with render prop" />
    <Example code={delayStart} title="Delay start" />
    <GithubCorner bannerColor="palevioletred" href={repo} />

);

export default App;
<commit_msg>Improve error<commit_after>import React, { Component, Fragment } from 'react';
import CountUp from 'react-countup';
import { description, repository } from 'react-countup/package';
import { RotateCw } from 'react-feather';
import GithubCorner from 'react-github-corner';
import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live';
import styled from 'styled-components';

const RefreshButton = styled.button`
  background: none;
  border: none;
  color: slategray;
  opacity: 0.5;
  outline: none;
  padding: 0;
  position: absolute;
  right: 16px;
  top: 16px;
  transition: 0.2s;
  width: 16px;

  &:hover {
    opacity: 1;
  }
`;

const Editor = styled(LiveEditor).attrs({ style: { padding: 16 } })`
  font-family: 'Overpass Mono', monospace;
  overflow: auto;
`;

const Error = styled(LiveError)`
  background: palevioletred;
  color: white;
  grid-column: span 2;
  padding: 16px;
`;

class Example extends Component {
  refresh = () => this.forceUpdate();

  render() {
    const { children, code, title, ...rest } = this.props;

    return (
      <Fragment>
        <Fragment>
          <Subtitle>{title}</Subtitle>
          <Provider scope={{ CountUp }} code={code.trim()} {...rest}>
            <Editor />
            <RefreshButton onClick={this.refresh} title="Re-render">
              <RotateCw size={16} />
            </RefreshButton>
            <Preview />
            <Error />
          </Provider>
          {children}
        </Fragment>
      </Fragment>
    );
  }
}

const Main = styled.main`
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
    sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
  margin: 32px auto;
  max-width: 960px;
`;

const Preview = styled(LivePreview)`
  align-items: center;
  background: whitesmoke;
  display: flex;
  justify-content: center;
  min-height: 64px;
  padding: 16px;

  & div {
    align-items: center;
    display: flex;
    flex-direction: column;
  }

  & span {
    display: flex;
    justify-content: center;
  }

  & button {
    background: white;
    border: none;
    border-radius: 4px;
    box-shadow: 0 4px 8px gainsboro;
    display: block;
    font-family: inherit;
    font-size: inherit;
    margin: 16px 0 auto;
    outline: none;
    padding: 8px 32px;

    &:active {
      transform: translateY(2px);
    }

    &:hover {
      background: snow;
    }
  }
`;

const Provider = styled(LiveProvider)`
  border-radius: 8px;
  box-shadow: 0 4px 8px gainsboro;
  overflow: hidden;
  display: grid;
  grid-template-columns: repeat(2, 50%);
  position: relative;
`;

const Subtitle = styled.h2`
  margin-top: 2em;
`;
const Text = styled.p``;
const Title = styled.h1``;

const simple = `
<CountUp end={123456} />
`;

const renderProp = `
<CountUp
  className="account-balance"
  start={-875.039}
  end={160527.012}
  duration={2.75}
  separator=" "
  decimals={4}
  decimal=","
  prefix="EUR "
  suffix=" left"
  onEnd={() => console.log('Ended! 👏')}
  onStart={() => console.log('Started! 💨')}
  >
  {({ countUpRef, start }) => (

      <button onClick={start}>Start</button>

  )}
</CountUp>
`;

const autoStart = `
<CountUp start={0} end={100} delay={0}>
  {({ countUpRef, start }) => (

      <button onClick={start}>Start</button>

  )}
</CountUp>
`;

const delayStart = `
<CountUp delay={2} end={100} />
`;

const repo = `https://github.com/${repository}`;

const App = () => (

    <Title>React CountUp</Title>
    <Text>{description}</Text>
    <Text>
      <a href={`${repo}#installation`}>Installation
      {' · '}
      <a href={`${repo}#installation`}>API
    </Text>
    <Example code={simple} title="Simple">
      <Text>Edit the code to see live changes.</Text>
    </Example>
    <Example code={renderProp} title="Render prop" />
    <Example code={autoStart} title="Autostart with render prop" />
    <Example code={delayStart} title="Delay start" />
    <GithubCorner bannerColor="palevioletred" href={repo} />

);

export default App;
<|endoftext|>


<commit_before>const uuid = require('uuid')
const inherits = require('util').inherits
const requestBuilder = require('./httpRequestBuilder')

function RequestIterator (requests, defaults) {
  if (!(this instanceof RequestIterator)) {
    return new RequestIterator(requests, defaults)
  }

  this.reqDefaults = defaults
  this.requestBuilder = requestBuilder(defaults)
  this.setRequests(requests)
}

inherits(RequestIterator, Object)

RequestIterator.prototype.nextRequest = function () {
  ++this.currentRequestIndex
  this.currentRequestIndex = this.currentRequestIndex < this.requests.length ? this.currentRequestIndex : 0
  this.currentRequest = this.requests[this.currentRequestIndex]
  return this.currentRequest
}

RequestIterator.prototype.nextRequestBuffer = function () {
  // get next request
  this.nextRequest()
  return this.currentRequest.requestBuffer
}

RequestIterator.prototype.move = function () {
  // get the current buffer and proceed to next request
  const ret = Buffer.from(this.currentRequest.requestBuffer.toString().replace(/\[<uuid>\]/g, uuid.v4()))
  this.nextRequest()
  return ret
}

RequestIterator.prototype.setRequests = function (newRequests) {
  this.requests = newRequests || [{}]
  this.currentRequestIndex = 0
  this.currentRequest = this.requests[0]
  this.rebuildRequests()
}

RequestIterator.prototype.rebuildRequests = function () {
  this.requests.forEach((request) => {
    request.requestBuffer = this.requestBuilder(request)
  })
}

RequestIterator.prototype.setHeaders = function (newHeaders) {
  this.currentRequest.headers = newHeaders || {}
  this.rebuildRequest()
}

RequestIterator.prototype.setBody = function (newBody) {
  this.currentRequest.body = newBody || new Buffer(0)
  this.rebuildRequest()
}

RequestIterator.prototype.setHeadersAndBody = function (newHeaders, newBody) {
  this.currentRequest.headers = newHeaders || {}
  this.currentRequest.body = newBody || new Buffer(0)
  this.rebuildRequest()
}

RequestIterator.prototype.setRequest = function (newRequest) {
  this.currentRequest = newRequest || {}
  this.rebuildRequest()
}

RequestIterator.prototype.rebuildRequest = function () {
  this.currentRequest.requestBuffer = this.requestBuilder(this.currentRequest)
  this.requests[this.currentRequestIndex] = this.currentRequest
}

module.exports = RequestIterator
<commit_msg>Amended Request Iterator to use Buffer constructor rather than Buffer_from function in order to ensure Node <6 compatibility<commit_after>const uuid = require('uuid')
const inherits = require('util').inherits
const requestBuilder = require('./httpRequestBuilder')

function RequestIterator (requests, defaults) {
  if (!(this instanceof RequestIterator)) {
    return new RequestIterator(requests, defaults)
  }

  this.reqDefaults = defaults
  this.requestBuilder = requestBuilder(defaults)
  this.setRequests(requests)
}

inherits(RequestIterator, Object)

RequestIterator.prototype.nextRequest = function () {
  ++this.currentRequestIndex
  this.currentRequestIndex = this.currentRequestIndex < this.requests.length ? this.currentRequestIndex : 0
  this.currentRequest = this.requests[this.currentRequestIndex]
  return this.currentRequest
}

RequestIterator.prototype.nextRequestBuffer = function () {
  // get next request
  this.nextRequest()
  return this.currentRequest.requestBuffer
}

RequestIterator.prototype.move = function () {
  // get the current buffer and proceed to next request
  const ret = new Buffer(this.currentRequest.requestBuffer.toString().replace(/\[<uuid>\]/g, uuid.v4()))
  this.nextRequest()
  return ret
}

RequestIterator.prototype.setRequests = function (newRequests) {
  this.requests = newRequests || [{}]
  this.currentRequestIndex = 0
  this.currentRequest = this.requests[0]
  this.rebuildRequests()
}

RequestIterator.prototype.rebuildRequests = function () {
  this.requests.forEach((request) => {
    request.requestBuffer = this.requestBuilder(request)
  })
}

RequestIterator.prototype.setHeaders = function (newHeaders) {
  this.currentRequest.headers = newHeaders || {}
  this.rebuildRequest()
}

RequestIterator.prototype.setBody = function (newBody) {
  this.currentRequest.body = newBody || new Buffer(0)
  this.rebuildRequest()
}

RequestIterator.prototype.setHeadersAndBody = function (newHeaders, newBody) {
  this.currentRequest.headers = newHeaders || {}
  this.currentRequest.body = newBody || new Buffer(0)
  this.rebuildRequest()
}

RequestIterator.prototype.setRequest = function (newRequest) {
  this.currentRequest = newRequest || {}
  this.rebuildRequest()
}

RequestIterator.prototype.rebuildRequest = function () {
  this.currentRequest.requestBuffer = this.requestBuilder(this.currentRequest)
  this.requests[this.currentRequestIndex] = this.currentRequest
}

module.exports = RequestIterator
<|endoftext|>


<commit_before>/*
 * For serving resource
 */

var express = require("express");

var Q = require("q");

module.exports = function ($config, http, $invokeFx) {

    var retVal = Q.defer();

    var express = require("express");
    var expressApp = express();

    expressApp.set("view engine", "jade");
    expressApp.set("views", "./client/view");

    http.on("request", expressApp);

    var resolveParameterFx = buildResolveParameterFx(expressApp);

    Q($invokeFx(require("./base-start/resources.js"), null, resolveParameterFx))
            .then(function () {
                return Q($invokeFx(require("../start/resources.js"), null, resolveParameterFx));
            })
            .then(function () {
                expressApp.get("*", function (req, res) {
                    var message = $config.name + ": ";
                    if (req.url == "/") {
                        message += "Hello world!";
                    } else {
                        message += "Page not found";
                    }
                    res.end(message);
                });
                retVal.resolve();
            })
            .fail(function (error) {
                retVal.reject(error);
            });

    return retVal.promise;
};

function buildResolveParameterFx(expressApp) {
    return function (parameter) {
        var retVal = null;

        switch (parameter) {
            case "$getResourceFx":
            {
                retVal = buildGetResourceFx(expressApp);
                break;
            }
            case "$postResourceFx":
            {
                retVal = buildPostResourceFx(expressApp);
                break;
            }
            case "$useStaticResourceFx":
            {
                retVal = buildUseStaticResourceFx(expressApp);
                break;
            }
        }
        return retVal;
    };
}

function buildGetResourceFx(expressApp) {
    return function (name, callback) {
        expressApp.get(name, callback);
    };
}

function buildPostResourceFx(expressApp) {
    return function (name, callback) {
        expressApp.post(name, callback);
    };
}

function buildUseStaticResourceFx(expressApp) {
    return function (directory) {
        expressApp.use(express.static(directory));
    };
}<commit_msg>Add status code for default expressjs response<commit_after>/*
 * For serving resource
 */

var express = require("express");

var Q = require("q");

module.exports = function ($config, http, $invokeFx) {

    var retVal = Q.defer();

    var express = require("express");
    var expressApp = express();

    expressApp.set("view engine", "jade");
    expressApp.set("views", "./client/view");

    http.on("request", expressApp);

    var resolveParameterFx = buildResolveParameterFx(expressApp);

    Q($invokeFx(require("./base-start/resources.js"), null, resolveParameterFx))
            .then(function () {
                return Q($invokeFx(require("../start/resources.js"), null, resolveParameterFx));
            })
            .then(function () {
                expressApp.get("*", function (req, res) {
                    var message = $config.name + ": ";
                    var status = 200;
                    if (req.url == "/") {
                        message += "Hello world!";
                    } else {
                        status = 400;
                        message += "Page not found";
                    }
                    res.status(status)
                            .end(message);
                });
                retVal.resolve();
            })
            .fail(function (error) {
                retVal.reject(error);
            });

    return retVal.promise;
};

function buildResolveParameterFx(expressApp) {
    return function (parameter) {
        var retVal = null;

        switch (parameter) {
            case "$getResourceFx":
            {
                retVal = buildGetResourceFx(expressApp);
                break;
            }
            case "$postResourceFx":
            {
                retVal = buildPostResourceFx(expressApp);
                break;
            }
            case "$useStaticResourceFx":
            {
                retVal = buildUseStaticResourceFx(expressApp);
                break;
            }
        }
        return retVal;
    };
}

function buildGetResourceFx(expressApp) {
    return function (name, callback) {
        expressApp.get(name, callback);
    };
}

function buildPostResourceFx(expressApp) {
    return function (name, callback) {
        expressApp.post(name, callback);
    };
}

function buildUseStaticResourceFx(expressApp) {
    return function (directory) {
        expressApp.use(express.static(directory));
    };
}<|endoftext|>


<commit_before>var crypto = require('crypto'),
    path = require('path'),
    fs = require('fs');

var uuid = require('node-uuid');

var db = require('../db.js'),
    util = require('../util'),
    defaults = require('../defaults.js'),
    settings = require('../settings');

function create_update(req, res, next) {
  settings.set(req.body);
  var error = settings.save();

  if(error) next(error);
  else res.json(201, settings.toJSON());
}
exports.create = exports.update = util.loginRequired(create_update);

function show(req, res) {
  res.json(settings.toJSON());
}
exports.show = util.loginRequired(show);

function connectionTest(req, res, next) {
  var sent = false;

  setTimeout(function() {
    sent = true;
    res.json(500, {code: 'ETIMEOUT', message: 'Failure: Timeout!'});
  }, 2000);

  db.connect(req.body.uri, function(err) {
    if(err) {
      if(err.code == 'ENOTFOUND') {
        err.message = 'Failure: Address not found!';
      }
      next(err);
    } else {
      if(!sent) {
        res.json(200, {ok: true});
      }
    }
  });
}
exports.connectionTest = connectionTest;

function tableCreation(req, res, next) {
  res.set('Content-Type','text/event-stream');

  db.syncDB({
    uri: req.query.uri,

    oncomplete: function(err) {
      if(err) return next(err);
      res.end('data: ' + JSON.stringify({done: true}) + '\n\n');
    },

    onprogress: function(script) {
      res.write('data: ' + JSON.stringify({script: script}) + '\n\n');
    },

    forceDrop: false
  });
}
exports.tableCreation = tableCreation;

function commit(req, res, next) {
  var body = req.body,
      obj = {
        DB: body.uri,
        SITE_ID: uuid.v4(),
        SECRET_KEY: crypto.randomBytes(64).toString('base64')
      };

  var err = settings.save(obj, settings.DEFAULT_FILENAME);
  if(err) {
    if(err.code == 'EACCES') {
      err.message = 'You don\'t have permission to write to `' + err.path + '`';
    }
    next(err);
  } else {
    res.json(201, {ok: true});
  }
}
exports.commit = commit;

function createUser(req, res, next) {
  var body = req.body;

  db.users.create(body, function(err, user) {
    if(err) return next(err);
    res.json(201, user);
  });
}
exports.createUser = createUser;<commit_msg>Don't take connection to the database for granted, run a query against it as well<commit_after>var crypto = require('crypto'),
    path = require('path'),
    fs = require('fs');

var uuid = require('node-uuid');

var db = require('../db.js'),
    util = require('../util'),
    defaults = require('../defaults.js'),
    settings = require('../settings');

function create_update(req, res, next) {
  settings.set(req.body);
  var error = settings.save();

  if(error) next(error);
  else res.json(201, settings.toJSON());
}
exports.create = exports.update = util.loginRequired(create_update);

function show(req, res) {
  res.json(settings.toJSON());
}
exports.show = util.loginRequired(show);

function connectionTest(req, res, next) {
  settings.set('DB', req.body.uri);

  db.query('SELECT NOW();', function(err) {
    if(err) {
      if(err.code == 'ENOTFOUND') {
        err.message = 'Failure: Address not found!';
      }
      next(err);
    } else {
      res.json(200, {ok: true});
    }
  });
}
exports.connectionTest = connectionTest;

function tableCreation(req, res, next) {
  res.set('Content-Type','text/event-stream');

  db.syncDB({
    oncomplete: function(err) {
      if(err) return next(err);
      res.end('data: ' + JSON.stringify({done: true}) + '\n\n');
    },

    onprogress: function(script) {
      res.write('data: ' + JSON.stringify({script: script}) + '\n\n');
    },

    forceDrop: false
  });
}
exports.tableCreation = tableCreation;

function commit(req, res, next) {
  var obj = {
      DB: settings.get('DB'),
      SITE_ID: uuid.v4(),
      SECRET_KEY: crypto.randomBytes(64).toString('base64')
    };

  var err = settings.save(obj, settings.DEFAULT_FILENAME);
  if(err) {
    if(err.code == 'EACCES') {
      err.message = 'You don\'t have permission to write to `' + err.path + '`';
    }
    next(err);
  } else {
    res.json(201, {ok: true});
  }
}
exports.commit = commit;

function createUser(req, res, next) {
  var body = req.body;

  db.users.create(body, function(err, user) {
    if(err) return next(err);
    res.json(201, user);
  });
}
exports.createUser = createUser;<|endoftext|>


<commit_before>// Load modules

var Stream = require('stream');
var Zlib = require('zlib');
var Negotiator = require('negotiator');
var Generic = require('./generic');
var Headers = require('./headers');
var Utils = require('../utils');

// Declare internals

var internals = {};

// Stream response (Generic -> Stream)

exports = module.exports = internals.Stream = function (stream) {

    Generic.call(this);
    this.variety = 'stream';
    this.varieties.stream = true;

    delete this._payload;

    this._passThrough = {};
    this._setStream(stream);

    return this;
};

Utils.inherits(internals.Stream, Generic);

internals.Stream.prototype.bytes = function (bytes) {

    this._headers['Content-Length'] = bytes;
    return this;
};

internals.Stream.prototype._setStream = function (stream) {

    if (!stream) {
        this._stream = null;
        return;
    }

    // Check if stream is a node HTTP response (stream.*) or a (mikeal's) Request object (stream.response.*)

    if (stream.statusCode ||
        (stream.response && stream.response.statusCode)) {

        this._passThrough.code = stream.statusCode || stream.response.statusCode;
    }

    if (stream.headers ||
        (stream.response && stream.response.headers)) {

        this._passThrough.headers = stream.headers || stream.response.headers;
    }

    // Support pre node v0.10 streams API

    if (stream.pipe === Stream.prototype.pipe) {

        var oldStream = stream;
        oldStream.pause();
        stream = new Stream.Readable().wrap(stream);
        oldStream.resume();
    }

    this._stream = stream;
};

internals.Stream.prototype._prepare = function (request, callback) {

    var self = this;

    this._wasPrepared = true;

    if (this._flags.location) {
        this._headers.Location = Headers.location(this._flags.location, request);
    }

    Headers.cache(this, request);
    Headers.cors(this, request);
    Headers.state(this, request, function (err) {

        if (err) {
            return callback(err);
        }

        Headers.auth(self, request, function (err) {

            return callback(err || self);
        });
    });
};

internals.Stream.prototype._transmit = function (request, callback) {

    var self = this;

    // Apply passthrough code and headers

    if (this._passThrough.headers &&
        (!request._route.proxy || request._route.proxy.settings.passThrough)) {

        if (this._passThrough.headers) {
            var localCookies = Utils.clone(this._headers['Set-Cookie']);
            var localHeaders = this._headers;
            this._headers = Utils.clone(this._passThrough.headers);
            Utils.merge(this._headers, localHeaders);

            if (localCookies) {
                var headerKeys = Object.keys(this._passThrough.headers);
                for (var i = 0, il = headerKeys.length; i < il; ++i) {

                    if (headerKeys[i].toLowerCase() === 'set-cookie') {
                        delete this._headers[headerKeys[i]];
                        this._headers['Set-Cookie'] = [].concat(this._passThrough.headers[headerKeys[i]]).concat(localCookies);
                        break;
                    }
                };
            }
        }
    }

    if (this._passThrough.code) {
        this._code = this._passThrough.code;
    }

    var encoder = null;
    if (!this._headers['content-encoding']) {
        var negotiator = new Negotiator(request.raw.req);
        var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
        if (encoding === 'deflate' || encoding === 'gzip') {
            Object.keys(this._headers).forEach(function (key) {

                if (/content\-length/i.test(key)) {                 // Can be lowercase when coming from proxy
                    delete self._headers[key];
                }
            });

            if (encoding === 'gzip') {
                this._headers['Content-Encoding'] = 'gzip';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createGzip();
            }

            if (encoding === 'deflate') {
                this._headers['Content-Encoding'] = 'deflate';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createDeflate();
            }
        }
    }

    Object.keys(this._headers).forEach(function (header) {

        request.raw.res.setHeader(header, self._headers[header]);
    });

    request.raw.res.writeHead(this._code);

    var end = function () {

        self._preview.end();
        self._preview.removeAllListeners();

        request.raw.res.end();

        self._stream.removeAllListeners();
        self._stream.destroy && self._stream.destroy();
        callback();
    };

    request.raw.req.once('close', end);
    this._stream.once('error', end);
    (encoder || this._stream).once('end', end);

    this._stream.pipe(this._preview);
    (encoder ? this._stream.pipe(encoder) : this._stream).pipe(request.raw.res, { end: false });
};
<commit_msg>Handle stream pipe better<commit_after>// Load modules

var Stream = require('stream');
var Zlib = require('zlib');
var Negotiator = require('negotiator');
var Generic = require('./generic');
var Headers = require('./headers');
var Utils = require('../utils');

// Declare internals

var internals = {};

// Stream response (Generic -> Stream)

exports = module.exports = internals.Stream = function (stream) {

    Generic.call(this);
    this.variety = 'stream';
    this.varieties.stream = true;

    delete this._payload;

    this._passThrough = {};
    this._setStream(stream);

    return this;
};

Utils.inherits(internals.Stream, Generic);

internals.Stream.prototype.bytes = function (bytes) {

    this._headers['Content-Length'] = bytes;
    return this;
};

internals.Stream.prototype._setStream = function (stream) {

    if (!stream) {
        this._stream = null;
        return;
    }

    // Check if stream is a node HTTP response (stream.*) or a (mikeal's) Request object (stream.response.*)

    if (stream.statusCode ||
        (stream.response && stream.response.statusCode)) {

        this._passThrough.code = stream.statusCode || stream.response.statusCode;
    }

    if (stream.headers ||
        (stream.response && stream.response.headers)) {

        this._passThrough.headers = stream.headers || stream.response.headers;
    }

    // Support pre node v0.10 streams API

    if (stream.pipe === Stream.prototype.pipe) {

        var oldStream = stream;
        oldStream.pause();
        stream = new Stream.Readable().wrap(oldStream);
        oldStream.resume();
    }

    this._stream = stream;
};

internals.Stream.prototype._prepare = function (request, callback) {

    var self = this;

    this._wasPrepared = true;

    if (this._flags.location) {
        this._headers.Location = Headers.location(this._flags.location, request);
    }

    Headers.cache(this, request);
    Headers.cors(this, request);
    Headers.state(this, request, function (err) {

        if (err) {
            return callback(err);
        }

        Headers.auth(self, request, function (err) {

            return callback(err || self);
        });
    });
};

internals.Stream.prototype._transmit = function (request, callback) {

    var self = this;

    // Apply passthrough code and headers

    if (this._passThrough.headers &&
        (!request._route.proxy || request._route.proxy.settings.passThrough)) {

        if (this._passThrough.headers) {
            var localCookies = Utils.clone(this._headers['Set-Cookie']);
            var localHeaders = this._headers;
            this._headers = Utils.clone(this._passThrough.headers);
            Utils.merge(this._headers, localHeaders);

            if (localCookies) {
                var headerKeys = Object.keys(this._passThrough.headers);
                for (var i = 0, il = headerKeys.length; i < il; ++i) {

                    if (headerKeys[i].toLowerCase() === 'set-cookie') {
                        delete this._headers[headerKeys[i]];
                        this._headers['Set-Cookie'] = [].concat(this._passThrough.headers[headerKeys[i]]).concat(localCookies);
                        break;
                    }
                };
            }
        }
    }

    if (this._passThrough.code) {
        this._code = this._passThrough.code;
    }

    var encoder = null;
    if (!this._headers['content-encoding']) {
        var negotiator = new Negotiator(request.raw.req);
        var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
        if (encoding === 'deflate' || encoding === 'gzip') {
            Object.keys(this._headers).forEach(function (key) {

                if (/content\-length/i.test(key)) {                 // Can be lowercase when coming from proxy
                    delete self._headers[key];
                }
            });

            if (encoding === 'gzip') {
                this._headers['Content-Encoding'] = 'gzip';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createGzip();
            }

            if (encoding === 'deflate') {
                this._headers['Content-Encoding'] = 'deflate';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createDeflate();
            }
        }
    }

    Object.keys(this._headers).forEach(function (header) {

        request.raw.res.setHeader(header, self._headers[header]);
    });

    request.raw.res.writeHead(this._code);

    var hasEnded = false;
    var end = function () {

        if (!hasEnded) {
            hasEnded = true;

            request.raw.res.end();

            self._preview.end();
            self._preview.removeAllListeners();

            self._stream.removeAllListeners();
            self._stream.destroy && self._stream.destroy();

            callback();
        }
    };

    this._stream.once('error', end);
    request.raw.req.once('close', end);
    request.raw.res.once('close', end);
    request.raw.res.once('end', end);

    this._stream.pipe(this._preview);
    (encoder ? this._stream.pipe(encoder) : this._stream).pipe(request.raw.res);
};
<|endoftext|>


<commit_before>// Load modules

var Stream = require('stream');
var Zlib = require('zlib');
var Negotiator = require('negotiator');
var Generic = require('./generic');
var Headers = require('./headers');
var Utils = require('../utils');

// Declare internals

var internals = {};

// Stream response (Generic -> Stream)

exports = module.exports = internals.Stream = function (stream) {

    Generic.call(this);
    this.variety = 'stream';
    this.varieties.stream = true;

    delete this._payload;

    this._passThrough = {};

    if (stream) {

        // Check if stream is a node HTTP response (stream.*) or a (mikeal's) Request object (stream.response.*)

        if (stream.statusCode ||
            (stream.response && stream.response.statusCode)) {

            this._passThrough.code = stream.statusCode || stream.response.statusCode;
        }

        if (stream.headers ||
            (stream.response && stream.response.headers)) {

            this._passThrough.headers = stream.headers || stream.response.headers;
        }

        // Support pre node v0.10 streams API

        if (stream.pipe === Stream.prototype.pipe) {

            var oldStream = stream;
            oldStream.pause();
            stream = new Stream.Readable().wrap(stream);
            oldStream.resume();
        }

        this._stream = stream;
    }

    return this;
};

Utils.inherits(internals.Stream, Generic);

internals.Stream.prototype.bytes = function (bytes) {

    this._headers['Content-Length'] = bytes;
    return this;
};

internals.Stream.prototype._prepare = function (request, callback) {

    var self = this;

    this._wasPrepared = true;

    if (this._flags.location) {
        this._headers.Location = Headers.location(this._flags.location, request);
    }

    Headers.cache(this, request);
    Headers.cors(this, request);
    Headers.state(this, request, function (err) {

        if (err) {
            return callback(err);
        }

        Headers.auth(self, request, function (err) {

            return callback(err || self);
        });
    });
};

internals.Stream.prototype._transmit = function (request, callback) {

    var self = this;

    // Apply passthrough code and headers

    if (this._passThrough.headers &&
        (!request._route.proxy || request._route.proxy.settings.passThrough)) {

        if (this._passThrough.headers) {
            var localCookies = Utils.clone(this._headers['Set-Cookie']);
            var localHeaders = this._headers;
            this._headers = Utils.clone(this._passThrough.headers);
            Utils.merge(this._headers, localHeaders);

            if (localCookies) {
                var headerKeys = Object.keys(this._passThrough.headers);
                for (var i = 0, il = headerKeys.length; i < il; ++i) {

                    if (headerKeys[i].toLowerCase() === 'set-cookie') {
                        delete this._headers[headerKeys[i]];
                        this._headers['Set-Cookie'] = [].concat(this._passThrough.headers[headerKeys[i]]).concat(localCookies);
                        break;
                    }
                };
            }
        }
    }

    if (this._passThrough.code) {
        this._code = this._passThrough.code;
    }

    var encoder = null;
    if (!this._headers['content-encoding']) {
        var negotiator = new Negotiator(request.raw.req);
        var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
        if (encoding === 'deflate' || encoding === 'gzip') {
            Object.keys(this._headers).forEach(function (key) {

                if (/content\-length/i.test(key)) {                 // Can be lowercase when coming from proxy
                    delete self._headers[key];
                }
            });

            if (encoding === 'gzip') {
                this._headers['Content-Encoding'] = 'gzip';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createGzip();
            }

            if (encoding === 'deflate') {
                this._headers['Content-Encoding'] = 'deflate';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createDeflate();
            }
        }
    }

    Object.keys(this._headers).forEach(function (header) {

        request.raw.res.setHeader(header, self._headers[header]);
    });

    request.raw.res.writeHead(this._code);

    var isEnded = false;
    var end = function () {

        if (isEnded) {
            return;
        }

        isEnded = true;
        self._preview.end();
        request.raw.res.end();
        callback();
    };

    request.raw.req.once('close', function () {

        end();
    });

    this._stream.once('error', function () {

        request.raw.req.destroy();
        end();
    });

    (encoder || this._stream).once('end', function () {

        end();
    });

    this._stream.pipe(this._preview);
    (encoder ? this._stream.pipe(encoder) : this._stream).pipe(request.raw.res, { end: false });
};
<commit_msg>Trying to solve #789<commit_after>// Load modules

var Stream = require('stream');
var Zlib = require('zlib');
var Negotiator = require('negotiator');
var Generic = require('./generic');
var Headers = require('./headers');
var Utils = require('../utils');

// Declare internals

var internals = {};

// Stream response (Generic -> Stream)

exports = module.exports = internals.Stream = function (stream) {

    Generic.call(this);
    this.variety = 'stream';
    this.varieties.stream = true;

    delete this._payload;

    this._passThrough = {};

    if (stream) {

        // Check if stream is a node HTTP response (stream.*) or a (mikeal's) Request object (stream.response.*)

        if (stream.statusCode ||
            (stream.response && stream.response.statusCode)) {

            this._passThrough.code = stream.statusCode || stream.response.statusCode;
        }

        if (stream.headers ||
            (stream.response && stream.response.headers)) {

            this._passThrough.headers = stream.headers || stream.response.headers;
        }

        // Support pre node v0.10 streams API

        if (stream.pipe === Stream.prototype.pipe) {

            var oldStream = stream;
            oldStream.pause();
            stream = new Stream.Readable().wrap(stream);
            oldStream.resume();
        }

        this._stream = stream;
    }

    return this;
};

Utils.inherits(internals.Stream, Generic);

internals.Stream.prototype.bytes = function (bytes) {

    this._headers['Content-Length'] = bytes;
    return this;
};

internals.Stream.prototype._prepare = function (request, callback) {

    var self = this;

    this._wasPrepared = true;

    if (this._flags.location) {
        this._headers.Location = Headers.location(this._flags.location, request);
    }

    Headers.cache(this, request);
    Headers.cors(this, request);
    Headers.state(this, request, function (err) {

        if (err) {
            return callback(err);
        }

        Headers.auth(self, request, function (err) {

            return callback(err || self);
        });
    });
};

internals.Stream.prototype._transmit = function (request, callback) {

    var self = this;

    // Apply passthrough code and headers

    if (this._passThrough.headers &&
        (!request._route.proxy || request._route.proxy.settings.passThrough)) {

        if (this._passThrough.headers) {
            var localCookies = Utils.clone(this._headers['Set-Cookie']);
            var localHeaders = this._headers;
            this._headers = Utils.clone(this._passThrough.headers);
            Utils.merge(this._headers, localHeaders);

            if (localCookies) {
                var headerKeys = Object.keys(this._passThrough.headers);
                for (var i = 0, il = headerKeys.length; i < il; ++i) {

                    if (headerKeys[i].toLowerCase() === 'set-cookie') {
                        delete this._headers[headerKeys[i]];
                        this._headers['Set-Cookie'] = [].concat(this._passThrough.headers[headerKeys[i]]).concat(localCookies);
                        break;
                    }
                };
            }
        }
    }

    if (this._passThrough.code) {
        this._code = this._passThrough.code;
    }

    var encoder = null;
    if (!this._headers['content-encoding']) {
        var negotiator = new Negotiator(request.raw.req);
        var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
        if (encoding === 'deflate' || encoding === 'gzip') {
            Object.keys(this._headers).forEach(function (key) {

                if (/content\-length/i.test(key)) {                 // Can be lowercase when coming from proxy
                    delete self._headers[key];
                }
            });

            if (encoding === 'gzip') {
                this._headers['Content-Encoding'] = 'gzip';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createGzip();
            }

            if (encoding === 'deflate') {
                this._headers['Content-Encoding'] = 'deflate';
                this._headers.Vary = 'Accept-Encoding';
                encoder = Zlib.createDeflate();
            }
        }
    }

    Object.keys(this._headers).forEach(function (header) {

        request.raw.res.setHeader(header, self._headers[header]);
    });

    request.raw.res.writeHead(this._code);

    var isEnded = false;
    var end = function () {

        if (isEnded) {
            return;
        }

        isEnded = true;
        self._preview.end();
        request.raw.res.end();
        self._stream.destroy && self._stream.destroy();
        callback();
    };

    request.raw.req.once('close', end);
    this._stream.once('error', end);
    (encoder || this._stream).once('end', end);

    this._stream.pipe(this._preview);
    (encoder ? this._stream.pipe(encoder) : this._stream).pipe(request.raw.res, { end: false });
};
<|endoftext|>


<commit_before>/**
 * Copyright reelyActive 2015
 * We believe in an open Internet of Things
 */

var MESSAGE_OK = "ok";
var MESSAGE_CREATED = "created";
var MESSAGE_NOTFOUND = "notFound";
var MESSAGE_BADREQUEST = "badRequest";
var MESSAGE_NOTIMPLEMENTED = "notImplemented";
var CODE_OK = 200;
var CODE_CREATED = 201;
var CODE_NOTFOUND = 404;
var CODE_BADREQUEST = 400;
var CODE_NOTIMPLEMENTED = 501;

/**
 * Prepares the JSON for an API query response which is successful
 * @param {Number} status Integer status code
 * @param {Object} req The request
 * @param {Object} data The data to include in the response
 */
function prepareResponse(status, req, data) {
  var response = {};
  prepareMeta(response, status);
  if(req) {
    prepareLinks(response, req);
  }
  if(data) {
    prepareData(response, req, data);
  }
  return response;
};

/**
 * Prepares and adds the _meta to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {Number} status Integer status code
 */
function prepareMeta(response, status) {
  switch(status) {
    case CODE_OK:
      response._meta = { "message": MESSAGE_OK,
                         "statusCode": CODE_OK };
      break;
    case CODE_CREATED:
      response._meta = { "message": MESSAGE_CREATED,
                         "statusCode": CODE_CREATED };
      break;
    case CODE_NOTFOUND:
      response._meta = { "message": MESSAGE_NOTFOUND,
                         "statusCode": CODE_NOTFOUND };
      break;
    case CODE_NOTIMPLEMENTED:
      response._meta = { "message": MESSAGE_NOTIMPLEMENTED,
                         "statusCode": CODE_NOTIMPLEMENTED };
      break;
    default:
      response._meta = { "message": MESSAGE_BADREQUEST,
                         "statusCode": CODE_BADREQUEST };
  }
};

/**
 * Prepares and adds the _links to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {Object} req The request
 */
function prepareLinks(response, req) {
  var rootUrl = req.protocol + '://' + req.get('host');
  var queryPath = req.originalUrl;
  var selfLink = { "href": rootUrl + queryPath };
  response._links = {};
  response._links["self"] = selfLink;
}

/**
 * Prepares and adds the data to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {Object} req The request
 * @param {Object} data The data to include in the response
 */
function prepareData(response, req, data) {
  var rootUrl = req.protocol + '://' + req.get('host');
  if(data.places) {
    var places = data.places;
    for(place in places) {
      places[place].href = rootUrl + "/at/" + place;
    }
    response.places = places;
  }
  if(data.devices) {
    var devices = data.devices;
    for(device in devices) {
      devices[device].href = rootUrl + "/id/" + device;
    }
    response.devices = devices;
  }
}

module.exports.OK = CODE_OK;
module.exports.CREATED = CODE_CREATED;
module.exports.NOTFOUND = CODE_NOTFOUND;
module.exports.BADREQUEST = CODE_BADREQUEST;
module.exports.NOTIMPLEMENTED = CODE_NOTIMPLEMENTED;
module.exports.prepareResponse = prepareResponse;
<commit_msg>Removed req in favour of rootUrl and queryPath<commit_after>/**
 * Copyright reelyActive 2015
 * We believe in an open Internet of Things
 */

var MESSAGE_OK = "ok";
var MESSAGE_CREATED = "created";
var MESSAGE_NOTFOUND = "notFound";
var MESSAGE_BADREQUEST = "badRequest";
var MESSAGE_NOTIMPLEMENTED = "notImplemented";
var CODE_OK = 200;
var CODE_CREATED = 201;
var CODE_NOTFOUND = 404;
var CODE_BADREQUEST = 400;
var CODE_NOTIMPLEMENTED = 501;

/**
 * Prepares the JSON for an API query response which is successful
 * @param {Number} status Integer status code
 * @param {String} rootUrl The root URL of the original query.
 * @param {String} queryPath The query path of the original query.
 * @param {Object} data The data to include in the response
 */
function prepareResponse(status, rootUrl, queryPath, data) {
  var response = {};
  prepareMeta(response, status);
  if(rootUrl && queryPath) {
    prepareLinks(response, rootUrl, queryPath);
  }
  if(data) {
    prepareData(response, rootUrl, data);
  }
  return response;
};

/**
 * Prepares and adds the _meta to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {Number} status Integer status code
 */
function prepareMeta(response, status) {
  switch(status) {
    case CODE_OK:
      response._meta = { "message": MESSAGE_OK,
                         "statusCode": CODE_OK };
      break;
    case CODE_CREATED:
      response._meta = { "message": MESSAGE_CREATED,
                         "statusCode": CODE_CREATED };
      break;
    case CODE_NOTFOUND:
      response._meta = { "message": MESSAGE_NOTFOUND,
                         "statusCode": CODE_NOTFOUND };
      break;
    case CODE_NOTIMPLEMENTED:
      response._meta = { "message": MESSAGE_NOTIMPLEMENTED,
                         "statusCode": CODE_NOTIMPLEMENTED };
      break;
    default:
      response._meta = { "message": MESSAGE_BADREQUEST,
                         "statusCode": CODE_BADREQUEST };
  }
};

/**
 * Prepares and adds the _links to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {String} rootUrl The root URL of the original query.
 * @param {String} queryPath The query path of the original query.
 */
function prepareLinks(response, rootUrl, queryPath) {
  var selfLink = { "href": rootUrl + queryPath };
  response._links = {};
  response._links["self"] = selfLink;
}

/**
 * Prepares and adds the devices to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {String} rootUrl The root URL of the original query.
 * @param {Object} data The data to include in the response
 */
function prepareData(response, rootUrl, data) {
  if(data.places) {
    var places = data.places;
    for(place in places) {
      places[place].href = rootUrl + "/at/" + place;
    }
    response.places = places;
  }
  if(data.devices) {
    var devices = data.devices;
    for(device in devices) {
      devices[device].href = rootUrl + "/id/" + device;
    }
    response.devices = devices;
  }
}

module.exports.OK = CODE_OK;
module.exports.CREATED = CODE_CREATED;
module.exports.NOTFOUND = CODE_NOTFOUND;
module.exports.BADREQUEST = CODE_BADREQUEST;
module.exports.NOTIMPLEMENTED = CODE_NOTIMPLEMENTED;
module.exports.prepareResponse = prepareResponse;
<|endoftext|>


<commit_before>export default function ($ionicPlatform) {

  'ngInject';
  $ionicPlatform.ready(function () {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    console.log('Cordova Run')
    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);
    }
    if (window.StatusBar) {
      // Set the statusbar to use the default style, tweak this to
      // remove the status bar on iOS or change it to use white instead of dark colors.
      StatusBar.styleDefault();
    }
  });
}
gi t<commit_msg>cordova config<commit_after>export default function ($ionicPlatform) {

  'ngInject';
  $ionicPlatform.ready(function () {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    console.log('Cordova Run')
    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);
    }
    if (window.StatusBar) {
      // Set the statusbar to use the default style, tweak this to
      // remove the status bar on iOS or change it to use white instead of dark colors.
      StatusBar.styleDefault();
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _message = require('./message');

var _message2 = _interopRequireDefault(_message);

var _messageBlock = require('./message-block');

var _messageBlock2 = _interopRequireDefault(_messageBlock);

var _config = require('./config');

var _config2 = _interopRequireDefault(_config);

var _tbSerializer = require('./tb-serializer');

var _tbSerializer2 = _interopRequireDefault(_tbSerializer);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// 単独タグ正規表現
var noEndTagRegExp = /<([a-z\-\_]+) \/>/g;
// 顔グラ変更命令正規表現
var faceCommandRegExp = /^\[([^\]]+)]$/;

var ScenarioParser = function () {
  function ScenarioParser(style) {
    var _this = this;

    var faces = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];

    _classCallCheck(this, ScenarioParser);

    this.continueTag = '';
    this.config = new _config2.default();
    this.config.loadStyleYaml(style);
    faces.forEach(function (face) {
      _this.config.loadPersonYaml(face);
    });
    this.serializer = new _tbSerializer2.default(this.config);
    this.parsedMessages = false;
  }

  _createClass(ScenarioParser, [{
    key: 'parse',
    value: function parse(input) {
      var _this2 = this;

      // trimと配列化
      var textList = input.split("\n").map(function (value) {
        return value.trim();
      });

      // 継続タグの初期化
      this.continuetag = '';

      // limit別に分ける
      var result = [];
      var tmp = [];
      var block = new _messageBlock2.default(false);
      textList.forEach(function (text) {
        if (_this2.config.hasFace && faceCommandRegExp.test(text)) {
          // 顔グラ変更
          var faceCommand = text.substr(1, text.length - 2);
          var faceConfig = _this2.config.getFace(faceCommand);
          if (!faceConfig) {
            throw new Error('未知の顔グラフィックです。：' + faceCommand);
          }
          // メッセージブロックの作り直し
          if (tmp.length > 0) {
            block.addMessage(_this2._tagFormat(tmp));
            tmp = [];
          }
          if (block.hasMessage()) {
            result.push(block);
          }
          block = new _messageBlock2.default(faceConfig);
          return; //continue
        }
        tmp.push(text);
        if (tmp.length == _this2.config.lineLimit) {
          block.addMessage(_this2._tagFormat(tmp));
          tmp = [];
        }
      });
      if (tmp.length > 0) {
        block.addMessage(this._tagFormat(tmp));
      }
      if (block.hasMessage()) {
        result.push(block);
      }

      this.parsedMessages = result;

      return result;
    }
  }, {
    key: 'serialize',
    value: function serialize() {
      if (!this.parsedMessages) {
        return '';
      }
      return this.serializer.serialize(this.parsedMessages);
    }
  }, {
    key: '_tagFormat',
    value: function _tagFormat(textList) {
      var _this3 = this;

      // 前回からの継続タグを追加
      var input = this.continueTag + textList.join("\n").replace(noEndTagRegExp, "<$1></$1>");
      // 継続タグのチェック
      var stack = [];
      var tags = input.match(/.?<\/?[a-z\_\-]+>/g);
      if (tags) {
        tags.forEach(function (tag) {
          if (tag.startsWith('\\')) {
            // エスケープ文字付きの場合対応しない
            return;
          }
          tag = tag.replace(/.?(<\/?[a-z\_\-]+>)/, '$1');
          if (tag.startsWith('</')) {
            // 閉じタグ
            var lastTag = stack.pop(tag);
            if (lastTag != tag.substr(2, tag.length - 3)) {
              throw new Error('タグの対応がおかしいです。: ' + lastTag);
            }
          } else {
            // 開始タグ
            stack.push(tag.substr(1, tag.length - 2));
          }
        });
      }
      if (stack.length > 0) {
        (function () {
          var prev = '';
          _this3.continueTag = stack.filter(function (v) {
            if (prev != v) {
              prev = v;
              return true;
            }
          }).map(function (v) {
            return '<' + v + '>';
          }).join('');
        })();
      }

      // 最終出力
      var output = input + stack.reverse().map(function (v) {
        return '</' + v + '>';
      }).join('');

      return new _message2.default(output.trim().split("\n"));
    }
  }]);

  return ScenarioParser;
}();

exports.default = ScenarioParser;<commit_msg>初期化処理のバグ修正<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _message = require('./message');

var _message2 = _interopRequireDefault(_message);

var _messageBlock = require('./message-block');

var _messageBlock2 = _interopRequireDefault(_messageBlock);

var _config = require('./config');

var _config2 = _interopRequireDefault(_config);

var _tbSerializer = require('./tb-serializer');

var _tbSerializer2 = _interopRequireDefault(_tbSerializer);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// 単独タグ正規表現
var noEndTagRegExp = /<([a-z\-\_]+) \/>/g;
// 顔グラ変更命令正規表現
var faceCommandRegExp = /^\[([^\]]+)]$/;

var ScenarioParser = function () {
  function ScenarioParser(style) {
    var _this = this;

    var faces = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];

    _classCallCheck(this, ScenarioParser);

    this.continueTag = '';
    this.config = new _config2.default();
    this.config.loadStyleYaml(style);
    faces.forEach(function (face) {
      _this.config.loadPersonYaml(face);
    });
    this.serializer = new _tbSerializer2.default(this.config);
    this.parsedMessages = false;
  }

  _createClass(ScenarioParser, [{
    key: 'parse',
    value: function parse(input) {
      var _this2 = this;

      // trimと配列化
      var textList = input.split("\n").map(function (value) {
        return value.trim();
      });

      // 継続タグの初期化
      this.continueTag = '';

      // limit別に分ける
      var result = [];
      var tmp = [];
      var block = new _messageBlock2.default(false);
      textList.forEach(function (text) {
        if (_this2.config.hasFace && faceCommandRegExp.test(text)) {
          // 顔グラ変更
          var faceCommand = text.substr(1, text.length - 2);
          var faceConfig = _this2.config.getFace(faceCommand);
          if (!faceConfig) {
            throw new Error('未知の顔グラフィックです。：' + faceCommand);
          }
          // メッセージブロックの作り直し
          if (tmp.length > 0) {
            block.addMessage(_this2._tagFormat(tmp));
            tmp = [];
          }
          if (block.hasMessage()) {
            result.push(block);
          }
          block = new _messageBlock2.default(faceConfig);
          return; //continue
        }
        tmp.push(text);
        if (tmp.length == _this2.config.lineLimit) {
          block.addMessage(_this2._tagFormat(tmp));
          tmp = [];
        }
      });
      if (tmp.length > 0) {
        block.addMessage(this._tagFormat(tmp));
      }
      if (block.hasMessage()) {
        result.push(block);
      }

      this.parsedMessages = result;

      return result;
    }
  }, {
    key: 'serialize',
    value: function serialize() {
      if (!this.parsedMessages) {
        return '';
      }
      return this.serializer.serialize(this.parsedMessages);
    }
  }, {
    key: '_tagFormat',
    value: function _tagFormat(textList) {
      var _this3 = this;

      // 前回からの継続タグを追加
      var input = this.continueTag + textList.join("\n").replace(noEndTagRegExp, "<$1></$1>");
      // 継続タグのチェック
      var stack = [];
      var tags = input.match(/.?<\/?[a-z\_\-]+>/g);
      if (tags) {
        tags.forEach(function (tag) {
          if (tag.startsWith('\\')) {
            // エスケープ文字付きの場合対応しない
            return;
          }
          tag = tag.replace(/.?(<\/?[a-z\_\-]+>)/, '$1');
          if (tag.startsWith('</')) {
            // 閉じタグ
            var lastTag = stack.pop(tag);
            if (lastTag != tag.substr(2, tag.length - 3)) {
              throw new Error('タグの対応がおかしいです。: ' + lastTag);
            }
          } else {
            // 開始タグ
            stack.push(tag.substr(1, tag.length - 2));
          }
        });
      }
      if (stack.length > 0) {
        (function () {
          var prev = '';
          _this3.continueTag = stack.filter(function (v) {
            if (prev != v) {
              prev = v;
              return true;
            }
          }).map(function (v) {
            return '<' + v + '>';
          }).join('');
        })();
      }

      // 最終出力
      var output = input + stack.reverse().map(function (v) {
        return '</' + v + '>';
      }).join('');

      return new _message2.default(output.trim().split("\n"));
    }
  }]);

  return ScenarioParser;
}();

exports.default = ScenarioParser;<|endoftext|>


<commit_before>var React  = require('react'),
    assign = require('object-assign');

var Tooltip = React.createClass({
    displayName: 'JoyrideTooltip',

    propTypes: {
        animate: React.PropTypes.bool.isRequired,
        browser: React.PropTypes.string.isRequired,
        buttons: React.PropTypes.object.isRequired,
        cssPosition: React.PropTypes.string.isRequired,
        onClick: React.PropTypes.func.isRequired,
        showOverlay: React.PropTypes.bool.isRequired,
        standalone: React.PropTypes.bool,
        step: React.PropTypes.object.isRequired,
        xPos: React.PropTypes.oneOfType([
            React.PropTypes.number,
            React.PropTypes.string
        ]).isRequired,
        yPos: React.PropTypes.oneOfType([
            React.PropTypes.number,
            React.PropTypes.string
        ]).isRequired
    },

    getDefaultProps: function () {
        return {
            browser: 'chrome',
            buttons: {
                primary: 'Close'
            },
            cssPosition: 'absolute',
            step: {},
            xPos: -1000,
            yPos: -1000
        };
    },

    _getArrowPosition: function (position) {
        var arrowPosition;

        if (window.innerWidth < 480) {
            arrowPosition = (position < 8 ? 8 : (position > 92 ? 92 : position));
        }
        else if (window.innerWidth < 1024) {
            arrowPosition = (position < 6 ? 6 : (position > 94 ? 94 : position));
        }
        else {
            arrowPosition = (position < 5 ? 5 : (position > 95 ? 95 : position));
        }

        return arrowPosition;
    },

    _generateArrow: function (opts) {
        var width,
            height,
            rotate;

        opts = opts || {};
        opts.location = opts.location || 'top';
        opts.color = opts.color || '#f04';
        opts.color = opts.color.replace('#', '%23');

        opts.width = opts.width || 36;
        opts.height = opts.width / 2;
        opts.scale = opts.width / 16;
        opts.rotate = '0';

        height = opts.height;
        rotate = opts.rotate;
        width = opts.width;

        if (opts.location === 'bottom') {
            rotate = '180 8 4';
        }
        else if (opts.location === 'left') {
            height = opts.width;
            width = opts.height;
            rotate = '270 8 8';
        }
        else if (opts.location === 'right') {
            height = opts.width;
            width = opts.height;
            rotate = '90 4 4';
        }

        return 'data:image/svg+xml,%3Csvg%20width%3D%22' + width + '%22%20height%3D%22' + height + '%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpolygon%20points%3D%220%2C%200%208%2C%208%2016%2C0%22%20fill%3D%22' + opts.color + '%22%20transform%3D%22scale%28' + opts.scale + '%29%20rotate%28' + rotate + '%29%22%3E%3C%2Fpolygon%3E%3C%2Fsvg%3E';
    },

    render: function () {
        var props = this.props,
            step  = props.step,
            opts  = {
                classes: ['joyride-tooltip'],
                target: document.querySelector(step.selector).getBoundingClientRect(),
                positionClass: step.position,
                styles: {
                    arrow: {},
                    header: {},
                    hole: {},
                    buttons: {
                        primary: {},
                        textOnly: {}
                    },
                    tooltip: {
                        position: this.props.cssPosition === 'fixed' ? 'fixed' : 'absolute',
                        top: Math.round(this.props.yPos),
                        left: Math.round(this.props.xPos)
                    }
                }
            };

        opts.positonBaseClass = opts.positionClass.match(/-/) ? opts.positionClass.split('-')[0] : opts.positionClass;

        opts.styles.hole = {
            top: Math.round((opts.target.top - document.body.getBoundingClientRect().top) - 5),
            left: Math.round(opts.target.left - 5),
            width: Math.round(opts.target.width + 10),
            height: Math.round(opts.target.height + 10)
        };

        if ((/^bottom$/.test(opts.positionClass) || /^top$/.test(opts.positionClass)) && props.xPos > -1) {
            opts.tooltip = document.querySelector('.joyride-tooltip').getBoundingClientRect();
            opts.targetMiddle = (opts.target.left + opts.target.width / 2);
            opts.arrowPosition = (((opts.targetMiddle - props.xPos) / opts.tooltip.width) * 100).toFixed(2);
            opts.arrowPosition = this._getArrowPosition(opts.arrowPosition) + '%';

            opts.styles.arrow.left = opts.arrowPosition;
        }

        /* Styling */
        if (step.style) {
            if (step.style.backgroundColor) {
                opts.styles.arrow.backgroundImage = 'url("' + this._generateArrow({
                        location: opts.positonBaseClass,
                        color: step.style.backgroundColor
                    }) + '")';
                opts.styles.tooltip.backgroundColor = step.style.backgroundColor;
            }

            if (step.style.borderRadius) {
                opts.styles.tooltip.borderRadius = step.style.borderRadius;
            }

            if (step.style.color) {
                opts.styles.buttons.primary.color = step.style.color;
                opts.styles.buttons.textOnly.color = step.style.color;
                opts.styles.header.color = step.style.color;
                opts.styles.tooltip.color = step.style.color;
            }

            if (step.style.mainColor) {
                opts.styles.buttons.primary.backgroundColor = step.style.mainColor;
                opts.styles.header.borderColor = step.style.mainColor;
            }

            if (step.style.textAlign) {
                opts.styles.tooltip.textAlign = step.style.textAlign;
            }

            if (step.style.width) {
                opts.styles.tooltip.width = step.style.width;
            }

            if (step.style.button) {
                opts.styles.primary = assign(opts.styles.buttons.primary, step.style.button);
            }
        }

        if (props.standalone) {
            opts.classes.push('standalone');
        }
        if (opts.positonBaseClass) {
            opts.classes.push(opts.positonBaseClass);
        }
        opts.classes.push(opts.positionClass);
        if (props.animate) {
            opts.classes.push('animate');
        }

        if (step.title) {
            opts.header = (
                React.createElement('div', {
                    className: 'joyride-tooltip__header',
                    style: opts.styles.header
                }, step.title)
            );
        }

        opts.tooltipElement = React.createElement('div', {
                className: opts.classes.join(' '),
                style: opts.styles.tooltip,
                'data-target': step.selector
            },
            React.createElement('div', {
                className: 'triangle triangle-' + opts.positionClass,
                style: opts.styles.arrow
            }),
            React.createElement('a', {
                href: '#',
                className: 'joyride-tooltip__close' + (opts.header ? ' joyride-tooltip__close--header' : ''),
                style: opts.styles.buttons.textOnly,
                'data-type': 'close',
                onClick: props.onClick
            }, '×'),
            opts.header,
            React.createElement('div', {
                className: 'joyride-tooltip__main',
                dangerouslySetInnerHTML: { __html: step.text || '' }
            }),
            React.createElement('div', {
                    className: 'joyride-tooltip__footer'
                },
                (props.buttons.skip ?
                    React.createElement('a', {
                        href: '#',
                        className: 'skip',
                        style: opts.styles.buttons.textOnly,
                        'data-type': 'skip',
                        onClick: props.onClick
                    }, props.buttons.skip)
                    : false),
                (props.buttons.secondary ?
                    React.createElement('a', {
                        href: '#',
                        className: 'secondary',
                        style: opts.styles.buttons.textOnly,
                        'data-type': 'back',
                        onClick: props.onClick
                    }, props.buttons.secondary)
                    : false),
                React.createElement('a', {
                    href: '#',
                    className: 'primary',
                    style: opts.styles.buttons.primary,
                    'data-type': 'next',
                    onClick: props.onClick
                }, props.buttons.primary)
            )
        );

        if (props.showOverlay) {
            opts.hole = React.createElement('div', {
                className: 'joyride-hole ' + props.browser,
                style: opts.styles.hole
            });
        }

        if (!props.showOverlay) {
            return opts.tooltipElement;
        }

        return React.createElement('div', {
                className: 'joyride-overlay',
                style: {
                    height: document.body.clientHeight
                },
                'data-type': 'close',
                onClick: props.onClick
            },
            opts.hole,
            opts.tooltipElement
        );
    }
});

module.exports = Tooltip;
<commit_msg>refactor tooltip styling - independently back, skip and close options<commit_after>var React  = require('react'),
    assign = require('object-assign');

var Tooltip = React.createClass({
    displayName: 'JoyrideTooltip',

    propTypes: {
        animate: React.PropTypes.bool.isRequired,
        browser: React.PropTypes.string.isRequired,
        buttons: React.PropTypes.object.isRequired,
        cssPosition: React.PropTypes.string.isRequired,
        onClick: React.PropTypes.func.isRequired,
        showOverlay: React.PropTypes.bool.isRequired,
        standalone: React.PropTypes.bool,
        step: React.PropTypes.object.isRequired,
        xPos: React.PropTypes.oneOfType([
            React.PropTypes.number,
            React.PropTypes.string
        ]).isRequired,
        yPos: React.PropTypes.oneOfType([
            React.PropTypes.number,
            React.PropTypes.string
        ]).isRequired
    },

    getDefaultProps: function () {
        return {
            browser: 'chrome',
            buttons: {
                primary: 'Close'
            },
            cssPosition: 'absolute',
            step: {},
            xPos: -1000,
            yPos: -1000
        };
    },

    _getArrowPosition: function (position) {
        var arrowPosition;

        if (window.innerWidth < 480) {
            arrowPosition = (position < 8 ? 8 : (position > 92 ? 92 : position));
        }
        else if (window.innerWidth < 1024) {
            arrowPosition = (position < 6 ? 6 : (position > 94 ? 94 : position));
        }
        else {
            arrowPosition = (position < 5 ? 5 : (position > 95 ? 95 : position));
        }

        return arrowPosition;
    },

    _generateArrow: function (opts) {
        var width,
            height,
            rotate;

        opts = opts || {};
        opts.location = opts.location || 'top';
        opts.color = opts.color || '#f04';
        opts.color = opts.color.replace('#', '%23');

        opts.width = opts.width || 36;
        opts.height = opts.width / 2;
        opts.scale = opts.width / 16;
        opts.rotate = '0';

        height = opts.height;
        rotate = opts.rotate;
        width = opts.width;

        if (opts.location === 'bottom') {
            rotate = '180 8 4';
        }
        else if (opts.location === 'left') {
            height = opts.width;
            width = opts.height;
            rotate = '270 8 8';
        }
        else if (opts.location === 'right') {
            height = opts.width;
            width = opts.height;
            rotate = '90 4 4';
        }

        return 'data:image/svg+xml,%3Csvg%20width%3D%22' + width + '%22%20height%3D%22' + height + '%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpolygon%20points%3D%220%2C%200%208%2C%208%2016%2C0%22%20fill%3D%22' + opts.color + '%22%20transform%3D%22scale%28' + opts.scale + '%29%20rotate%28' + rotate + '%29%22%3E%3C%2Fpolygon%3E%3C%2Fsvg%3E';
    },

    _setStyles: function (opts, styles, stepStyles) {
        styles.hole = {
            top: Math.round((opts.target.top - document.body.getBoundingClientRect().top) - 5),
            left: Math.round(opts.target.left - 5),
            width: Math.round(opts.target.width + 10),
            height: Math.round(opts.target.height + 10)
        };

        styles.buttons = {
            back: {},
            close: {},
            primary: {},
            skip: {}
        };

        /* Styling */
        if (stepStyles) {
            if (stepStyles.backgroundColor) {
                styles.arrow.backgroundImage = 'url("' + this._generateArrow({
                        location: opts.positonBaseClass,
                        color: stepStyles.backgroundColor
                    }) + '")';
                styles.tooltip.backgroundColor = stepStyles.backgroundColor;
            }

            if (stepStyles.borderRadius) {
                styles.tooltip.borderRadius = stepStyles.borderRadius;
            }

            if (stepStyles.color) {
                styles.buttons.primary.color = stepStyles.color;
                styles.buttons.close.color = stepStyles.color;
                styles.buttons.skip.color = stepStyles.color;
                styles.header.color = stepStyles.color;
                styles.tooltip.color = stepStyles.color;

                if (stepStyles.mainColor && stepStyles.mainColor === stepStyles.color) {
                    styles.buttons.primary.color = stepStyles.backgroundColor;
                }
            }

            if (stepStyles.mainColor) {
                styles.buttons.primary.backgroundColor = stepStyles.mainColor;
                styles.buttons.back.color = stepStyles.mainColor;
                styles.header.borderColor = stepStyles.mainColor;
            }

            if (stepStyles.textAlign) {
                styles.tooltip.textAlign = stepStyles.textAlign;
            }

            if (stepStyles.width) {
                styles.tooltip.width = stepStyles.width;
            }

            if (stepStyles.back) {
                styles.buttons.back = assign(styles.buttons.back, stepStyles.back);
            }

            if (stepStyles.button) {
                styles.buttons.primary = assign(styles.buttons.primary, stepStyles.button);
            }

            if (stepStyles.close) {
                styles.buttons.close = assign(styles.buttons.close, stepStyles.close);
            }

            if (stepStyles.skip) {
                styles.buttons.skip = assign(styles.buttons.skip, stepStyles.skip);
            }
        }

        return styles;
    },

    render: function () {
        var props  = this.props,
            step   = props.step,
            opts   = {
                classes: ['joyride-tooltip'],
                target: document.querySelector(step.selector).getBoundingClientRect(),
                positionClass: step.position
            },
            styles = {
                arrow: {},
                buttons: {},
                header: {},
                hole: {},
                tooltip: {
                    position: this.props.cssPosition === 'fixed' ? 'fixed' : 'absolute',
                    top: Math.round(this.props.yPos),
                    left: Math.round(this.props.xPos)
                }
            };

        opts.positonBaseClass = opts.positionClass.match(/-/) ? opts.positionClass.split('-')[0] : opts.positionClass;

        if ((/^bottom$/.test(opts.positionClass) || /^top$/.test(opts.positionClass)) && props.xPos > -1) {
            opts.tooltip = document.querySelector('.joyride-tooltip').getBoundingClientRect();
            opts.targetMiddle = (opts.target.left + opts.target.width / 2);
            opts.arrowPosition = (((opts.targetMiddle - props.xPos) / opts.tooltip.width) * 100).toFixed(2);
            opts.arrowPosition = this._getArrowPosition(opts.arrowPosition) + '%';

            styles.arrow.left = opts.arrowPosition;
        }

        styles = this._setStyles(opts, styles, step.style)

        if (props.standalone) {
            opts.classes.push('standalone');
        }
        if (opts.positonBaseClass) {
            opts.classes.push(opts.positonBaseClass);
        }
        opts.classes.push(opts.positionClass);
        if (props.animate) {
            opts.classes.push('animate');
        }

        if (step.title) {
            opts.header = (
                React.createElement('div', {
                    className: 'joyride-tooltip__header',
                    style: styles.header
                }, step.title)
            );
        }

        opts.tooltipElement = React.createElement('div', {
                className: opts.classes.join(' '),
                style: styles.tooltip,
                'data-target': step.selector
            },
            React.createElement('div', {
                className: 'triangle triangle-' + opts.positionClass,
                style: styles.arrow
            }),
            React.createElement('a', {
                href: '#',
                className: 'joyride-tooltip__close' + (opts.header ? ' joyride-tooltip__close--header' : ''),
                style: styles.buttons.close,
                'data-type': 'close',
                onClick: props.onClick
            }, '×'),
            opts.header,
            React.createElement('div', {
                className: 'joyride-tooltip__main',
                dangerouslySetInnerHTML: { __html: step.text || '' }
            }),
            React.createElement('div', {
                    className: 'joyride-tooltip__footer'
                },
                (props.buttons.skip ?
                    React.createElement('a', {
                        href: '#',
                        className: 'skip',
                        style: styles.buttons.skip,
                        'data-type': 'skip',
                        onClick: props.onClick
                    }, props.buttons.skip)
                    : false),
                (props.buttons.secondary ?
                    React.createElement('a', {
                        href: '#',
                        className: 'secondary',
                        style: styles.buttons.back,
                        'data-type': 'back',
                        onClick: props.onClick
                    }, props.buttons.secondary)
                    : false),
                React.createElement('a', {
                    href: '#',
                    className: 'primary',
                    style: styles.buttons.primary,
                    'data-type': 'next',
                    onClick: props.onClick
                }, props.buttons.primary)
            )
        );

        if (props.showOverlay) {
            opts.hole = React.createElement('div', {
                className: 'joyride-hole ' + props.browser,
                style: styles.hole
            });
        }

        if (!props.showOverlay) {
            return opts.tooltipElement;
        }

        return React.createElement('div', {
                className: 'joyride-overlay',
                style: {
                    height: document.body.clientHeight
                },
                'data-type': 'close',
                onClick: props.onClick
            },
            opts.hole,
            opts.tooltipElement
        );
    }
});

module.exports = Tooltip;
<|endoftext|>