<commit_before>import { clean } from 'dom-clean'

const validAlias = /^[A-Za-z]+[\w\-]*$/

export default class DomPointer {
  constructor() {
    /**
     *
     * Original cleaned source template
     *
     * @type {DocumentFragment}
     */
    this.template = document.createDocumentFragment()

    /**
     *
     * Reference map
     *
     * If template is placed within the dom will point to the live dom.
     *
     * Otherwise it will point to the elements within the in-memory document fragment
     *
     * @type {Map}
     */
    this.refs = new Map()

    /**
     *
     * Cached alias mappings.
     *
     * Will be re-applied during each reset
     *
     * @type {Map}
     * @private
     */
    this._aliases = new Map()

    this._opts = {
      comments: true
    }

    /**
     *
     * Target element where this template is rendered
     *
     * @type {HTMLElement}
     */
    this.el = undefined

    /**
     *
     * The dom being prepared, while it's not yet placed within the dom itself.
     *
     * @type {DocumentFragment}
     * @private
     */
    this._swp = document.createDocumentFragment()
  }

  _parse(el, _p = []) {
    for (let idx = 0; idx < el.childNodes.length; idx++) {
      let node = el.childNodes[idx]
      const arr = _p.slice()
      arr.push(idx)

      if (node.nodeType === Node.COMMENT_NODE) {
        node = this._convertCommentToTextNode(node)
      }
      this.refs.set(':' + arr.join(':'), node)

      if (node.childNodes.length) {
        this._parse(node, arr)
      }
    }
  }

  /**
   *
   * Parses the given element and puts the references into this.refs
   *
   * Also converts any comments to text nodes to make them addressable entities
   *
   * @param {HTMLElement} el The Element
   * @param {Array} _p private path
   * @returns {DomPointer} This instance
   */
  parse(el) {
    this._parse(el)

    for (const [alias, path] of this._aliases) {
      this._alias(alias, path)
    }

    return this
  }

  /**
   *
   * Set target element
   *
   * @param {HTMLElement} el Target element for rendering
   * @returns {DomPointer} This instance
   */
  setElement(el) {
    this.el = el
    return this
  }

  /**
   * Set Options
   *
   * @param {Object} opts Options object
   * @param {Boolean} opts.comments Whether to keep comments
   * @returns {DomPointer} This instance
   */
  setOpts(opts = {}) {
    for (const key of Object.keys(opts)) {
      this._opts[key] = opts[key]
    }
    return this
  }

  _alias(alias, path) {
    if (validAlias.test(alias)) {
      this.refs.set(alias, this.getRef(path))
      return this
    }

    throw Error('Invalid alias: ' + alias)
  }

  /**
   *
   * Alias
   *
   * @param {String} alias Alias name
   * @param {String} path Path to be aliased
   * @returns {DomPointer} This instance
   */
  alias(alias, path) {
    this._alias(alias, path)
    this._aliases.set(alias, path)
  }

  /**
   *
   * Takes a HTMLElement and returns it's path relative to the base element
   *
   * @param {HTMLElement} el A HTML Element
   * @return {String} Path to this element relative to the base element.
   */
  path(el) {
    let node = el
    const path = []
    while (node.parentNode) {
      path.push(Array.prototype.indexOf.call(node.parentNode.childNodes, node))
      if (node.parentNode === this.el) {
        break
      }
      node = node.parentNode
    }
    return ':' + path.reverse().join(':')
  }

  /**
   *
   * Given some elements returns a named path map.
   *
   * @param {HTMLElement[]} els List of elements to include in the map
   * @returns {Object} Map with selected paths
   */
  paths(els) {
    const paths = {}
    for (const item of els) {
      paths[this.path(item)] = item
    }
    return paths
  }
  /**
   *
   * Create DomPointer from an existing element
   *
   * @param {HTMLElement} el HTMLElement
   * @param {Object} opts Options object
   * @return {DomPointer} Dom Pointer instance
   */
  static create(el, opts) {
    const dp = new DomPointer()
    dp.setOpts(opts)
    clean(el, dp._opts.comments)
    dp.setElement(el)
    dp.template.appendChild(
      el.cloneNode(true)
    )
    dp.reset()
    return dp
  }

  /**
   *
   * Create DomPointer from a string of HTML
   *
   * Use setElement to set the target element for rendering
   *
   * @param {String} html HTML String
   * @param {Object} opts Options object
   * @return {DomPointer} Dom Pointer instance
   */
  static fromHTML(html, opts) {
    const dp = new DomPointer()
    dp.setOpts(opts)
    dp.setHTML(html)
    dp.reset()
    return dp
  }

  /**
   *
   * Set HTML
   *
   * @param {String} html HTML String
   * @returns {DomPointer} Dom Pointer instance
   */
  setHTML(html) {
    const temp = document.createElement('div')
    temp.innerHTML = html
    clean(temp, this._opts.comments)
    while (temp.firstChild) {
      this.template.appendChild(temp.firstChild)
    }
    return this
  }

  _dealias(alias) {
    return this._aliases.has(alias) ? this._aliases.get(alias) : alias
  }

  /**
   *
   * Retrieve or set data for this node.
   *
   * Usage:
   *
   *   dp.data(':0:0:1', data);
   *
   * @param {String} path path
   * @param {mixed} val value to set
   * @param {String} cpath Path of the container node (defaults to parentNode)
   * @param {Boolean} append Whether to append to the contents
   * @returns {DomPointer} Dom Pointer instance
   */
  data(path, val, cpath, append) {
    const fpath = cpath ? this._dealias(cpath) + path : path
    const el = this.getRef(fpath)
    const method = el.nodeType === Node.TEXT_NODE ? 'nodeValue' : 'innerHTML'
    if (append) {
      el[method] += val
    } else {
      el[method] = val
    }
    return this
  }

  /**
   *
   * @param {HTMLElement} el HTMLElement
   * @returns {TextElement} TextNode
   * @private
   */
  _convertCommentToTextNode(el) {
    const nc = document.createTextNode('')
    el.parentNode.replaceChild(nc, el)
    return nc
  }

  /**
   *
   * Get reference by path.
   *
   * @param {String} path path
   * @returns {HTMLElement} HTML Element
   */
  getRef(path) {
    if (this.refs.has(path)) {
      return this.refs.get(path)
    }

    throw Error('Unknown path: ' + path)
  }

  /**
   *
   * Add attribute
   *
   * Will add an attribute:
   *
   *  { op: 'add', path: ':0:1', name: 'class', val: 'warning' }
   *
   * If the attribute already exists will append the value separated by a space
   *
   * @param {HTMLElement} el HTML Element
   * @param {Object} change Change object
   * @param {String} change.op The operation
   * @param {String} change.path The target path
   * @param {String} change.name Attribute name
   * @param {String} change.val Attribute value
   * @returns {Void} Void
   * @private
   */
  _addAttribute(el, change) {
    const curr = el.getAttribute(change.name)
    if (curr) {
      el.setAttribute(change.name, [curr, change.val].join(' '))
    } else {
      el.setAttribute(change.name, change.val)
    }
  }

  /**
   *
   * Removes an attribute
   *
   * Will remove the attribute entirely:
   *
   *  { op: 'remove', path: ':0:1', name: 'class' }
   *
   * If you specify a val and the attribute is a class
   * will only remove the value from the class list:
   *
   *  { op: 'remove', path: ':0:1', name: 'class', val: 'warning' }
   *
   * @param {HTMLElement} el HTML Element
   * @param {Object} change Change object
   * @param {String} change.op The operation
   * @param {String} change.path The target path
   * @param {String} change.name Attribute name
   * @param {String} change.val Attribute value
   * @returns {Void} Void
   * @private
   */
  _removeAttribute(el, change) {
    const curr = el.getAttribute(change.name)
    if (change.val) {
      if (curr) {
        const items = curr.split(' ')
        items.splice(
          items.indexOf(change.val), 1
        )
        el.setAttribute(change.name, items.join(' '))
      }
    } else {
      el.removeAttribute(change.name)
    }
  }

  setAttributes(map = []) {
    for (const change of map) {
      const el = this.refs.get(change.path)
      switch (change.op) {
      case 'remove':
        this._removeAttribute(el, change)
        break
      case 'add':
      case 'change':
      default:
        this._addAttribute(el, change)
        break
      }
    }
  }

  /**
   *
   * Resets and moves operation to the in-memory _swp fragment.
   * All operations will take place against _swp.
   *
   * Use the remove parameter to directly remove the current rendering
   * from the dom, else it will be replaced once render() is called again.
   *
   * When a fragment is placed it's references become live
   *
   * Reset sets the context to _swp again instead of what is present within the dom.
   *
   * @param {Boolean} remove Whether to remove the current rendering from the dom
   * @returns {DomPointer} Dom Pointer instance
   */
  reset(remove) {
    if (remove) {
      this.el.parentNode.removeChild(this.el)
    }
    this.refs.clear()
    this._swp.appendChild(
      this.template.cloneNode(true)
    )
    this.parse(this._swp)
    return this
  }

  /**
   * (Re)renders  the template.
   *
   * When render is called the current swp empties and the context of the references will be the live dom.
   *
   * @return {HTMLElement} The old childNode
   */
  render() {
    return this.el.replaceChild(this._swp, this.el.firstChild) // automatically clears this._swp
  }
}
<commit_msg>be less confusing<commit_after>import { clean } from 'dom-clean'

const validAlias = /^[A-Za-z]+[\w\-]*$/

export default class DomPointer {
  constructor() {
    /**
     *
     * Original cleaned source template
     *
     * @type {DocumentFragment}
     */
    this.template = document.createDocumentFragment()

    /**
     *
     * Reference map
     *
     * If template is placed within the dom will point to the live dom.
     *
     * Otherwise it will point to the elements within the in-memory document fragment
     *
     * @type {Map}
     */
    this.refs = new Map()

    /**
     *
     * Cached alias mappings.
     *
     * Will be re-applied during each reset
     *
     * @type {Map}
     * @private
     */
    this._aliases = new Map()

    this._opts = {
      comments: true
    }

    /**
     *
     * Target element where this template is rendered
     *
     * @type {HTMLElement}
     */
    this.el = undefined

    /**
     *
     * The dom being prepared, while it's not yet placed within the dom itself.
     *
     * @type {DocumentFragment}
     * @private
     */
    this._swp = document.createDocumentFragment()
  }

  _parse(el, _p = []) {
    for (let idx = 0; idx < el.childNodes.length; idx++) {
      let node = el.childNodes[idx]
      const arr = _p.slice()
      arr.push(idx)

      if (node.nodeType === Node.COMMENT_NODE) {
        node = this._convertCommentToTextNode(node)
      }
      this.refs.set(':' + arr.join(':'), node)

      if (node.childNodes.length) {
        this._parse(node, arr)
      }
    }
  }

  /**
   *
   * Parses the given element and puts the references into this.refs
   *
   * Also converts any comments to text nodes to make them addressable entities
   *
   * @param {HTMLElement} el The Element
   * @param {Array} _p private path
   * @returns {DomPointer} This instance
   */
  parse(el) {
    this._parse(el)

    for (const [alias, path] of this._aliases) {
      this._alias(alias, path)
    }

    return this
  }

  /**
   *
   * Set target element
   *
   * @param {HTMLElement} el Target element for rendering
   * @returns {DomPointer} This instance
   */
  setElement(el) {
    this.el = el
    return this
  }

  /**
   * Set Options
   *
   * @param {Object} opts Options object
   * @param {Boolean} opts.comments Whether to keep comments
   * @returns {DomPointer} This instance
   */
  setOpts(opts = {}) {
    for (const key of Object.keys(opts)) {
      this._opts[key] = opts[key]
    }
    return this
  }

  _alias(alias, path) {
    if (validAlias.test(alias)) {
      this.refs.set(alias, this.getRef(path))
      return this
    }

    throw Error('Invalid alias: ' + alias)
  }

  /**
   *
   * Alias
   *
   * @param {String} alias Alias name
   * @param {String} path Path to be aliased
   * @returns {DomPointer} This instance
   */
  alias(alias, path) {
    this._alias(alias, path)
    this._aliases.set(alias, path)
  }

  /**
   *
   * Takes a HTMLElement and returns it's path relative to the base element
   *
   * @param {HTMLElement} el A HTML Element
   * @return {String} Path to this element relative to the base element.
   */
  path(el) {
    let node = el
    const path = []
    while (node.parentNode) {
      path.push(Array.prototype.indexOf.call(node.parentNode.childNodes, node))
      if (node.parentNode === this.el) {
        break
      }
      node = node.parentNode
    }
    return ':' + path.reverse().join(':')
  }

  /**
   *
   * Given some elements returns a named path map.
   *
   * @param {HTMLElement[]} els List of elements to include in the map
   * @returns {Object} Map with selected paths
   */
  paths(els) {
    const paths = {}
    for (const item of els) {
      paths[this.path(item)] = item
    }
    return paths
  }
  /**
   *
   * Create DomPointer from an existing element
   *
   * @param {HTMLElement} el HTMLElement
   * @param {Object} opts Options object
   * @return {DomPointer} Dom Pointer instance
   */
  static create(el, opts) {
    const dp = new DomPointer()
    dp.setOpts(opts)
    clean(el, dp._opts.comments)
    dp.setElement(el)
    dp.template.appendChild(
      el.cloneNode(true)
    )
    dp.reset()
    return dp
  }

  /**
   *
   * Create DomPointer from a string of HTML
   *
   * Use setElement to set the target element for rendering
   *
   * @param {String} html HTML String
   * @param {Object} opts Options object
   * @return {DomPointer} Dom Pointer instance
   */
  static fromHTML(html, opts) {
    const dp = new DomPointer()
    dp.setOpts(opts)
    dp.setHTML(html)
    dp.reset()
    return dp
  }

  /**
   *
   * Set HTML
   *
   * @param {String} html HTML String
   * @returns {DomPointer} Dom Pointer instance
   */
  setHTML(html) {
    const temp = document.createElement('div')
    temp.innerHTML = html
    clean(temp, this._opts.comments)
    while (temp.firstChild) {
      this.template.appendChild(temp.firstChild)
    }
    return this
  }

  /**
   *
   * Dealias
   *
   * @param {String} path Path to be dealiased
   * @returns {String} Dealiased path
   * @private
   */
  _dealias(path) {
    return this._aliases.has(path) ? this._aliases.get(path) : path
  }

  /**
   *
   * Retrieve or set data for this node.
   *
   * Usage:
   *
   *   dp.data(':0:0:1', data);
   *
   * @param {String} path path
   * @param {mixed} val value to set
   * @param {String} cpath Path of the container node (defaults to parentNode)
   * @param {Boolean} append Whether to append to the contents
   * @returns {DomPointer} Dom Pointer instance
   */
  data(path, val, cpath, append) {
    const fpath = cpath ? this._dealias(cpath) + path : path
    const el = this.getRef(fpath)
    const method = el.nodeType === Node.TEXT_NODE ? 'nodeValue' : 'innerHTML'
    if (append) {
      el[method] += val
    } else {
      el[method] = val
    }
    return this
  }

  /**
   *
   * @param {HTMLElement} el HTMLElement
   * @returns {TextElement} TextNode
   * @private
   */
  _convertCommentToTextNode(el) {
    const nc = document.createTextNode('')
    el.parentNode.replaceChild(nc, el)
    return nc
  }

  /**
   *
   * Get reference by path.
   *
   * @param {String} path path
   * @returns {HTMLElement} HTML Element
   */
  getRef(path) {
    if (this.refs.has(path)) {
      return this.refs.get(path)
    }

    throw Error('Unknown path: ' + path)
  }

  /**
   *
   * Add attribute
   *
   * Will add an attribute:
   *
   *  { op: 'add', path: ':0:1', name: 'class', val: 'warning' }
   *
   * If the attribute already exists will append the value separated by a space
   *
   * @param {HTMLElement} el HTML Element
   * @param {Object} change Change object
   * @param {String} change.op The operation
   * @param {String} change.path The target path
   * @param {String} change.name Attribute name
   * @param {String} change.val Attribute value
   * @returns {Void} Void
   * @private
   */
  _addAttribute(el, change) {
    const curr = el.getAttribute(change.name)
    if (curr) {
      el.setAttribute(change.name, [curr, change.val].join(' '))
    } else {
      el.setAttribute(change.name, change.val)
    }
  }

  /**
   *
   * Removes an attribute
   *
   * Will remove the attribute entirely:
   *
   *  { op: 'remove', path: ':0:1', name: 'class' }
   *
   * If you specify a val and the attribute is a class
   * will only remove the value from the class list:
   *
   *  { op: 'remove', path: ':0:1', name: 'class', val: 'warning' }
   *
   * @param {HTMLElement} el HTML Element
   * @param {Object} change Change object
   * @param {String} change.op The operation
   * @param {String} change.path The target path
   * @param {String} change.name Attribute name
   * @param {String} change.val Attribute value
   * @returns {Void} Void
   * @private
   */
  _removeAttribute(el, change) {
    const curr = el.getAttribute(change.name)
    if (change.val) {
      if (curr) {
        const items = curr.split(' ')
        items.splice(
          items.indexOf(change.val), 1
        )
        el.setAttribute(change.name, items.join(' '))
      }
    } else {
      el.removeAttribute(change.name)
    }
  }

  setAttributes(map = []) {
    for (const change of map) {
      const el = this.refs.get(change.path)
      switch (change.op) {
      case 'remove':
        this._removeAttribute(el, change)
        break
      case 'add':
      case 'change':
      default:
        this._addAttribute(el, change)
        break
      }
    }
  }

  /**
   *
   * Resets and moves operation to the in-memory _swp fragment.
   * All operations will take place against _swp.
   *
   * Use the remove parameter to directly remove the current rendering
   * from the dom, else it will be replaced once render() is called again.
   *
   * When a fragment is placed it's references become live
   *
   * Reset sets the context to _swp again instead of what is present within the dom.
   *
   * @param {Boolean} remove Whether to remove the current rendering from the dom
   * @returns {DomPointer} Dom Pointer instance
   */
  reset(remove) {
    if (remove) {
      this.el.parentNode.removeChild(this.el)
    }
    this.refs.clear()
    this._swp.appendChild(
      this.template.cloneNode(true)
    )
    this.parse(this._swp)
    return this
  }

  /**
   * (Re)renders  the template.
   *
   * When render is called the current swp empties and the context of the references will be the live dom.
   *
   * @return {HTMLElement} The old childNode
   */
  render() {
    return this.el.replaceChild(this._swp, this.el.firstChild) // automatically clears this._swp
  }
}
<|endoftext|>


<commit_before>import 'bootstrap/dist/css/bootstrap.min.css'

import React from 'react'
import ReactDOM from 'react-dom'
import { applyMiddleware, createStore } from 'redux'
import { logger } from 'redux-logger'
import { Provider } from 'react-redux'
import { TouchBackend } from 'react-dnd-touch-backend'
import { DndProvider } from 'react-dnd'
import styled, { createGlobalStyle } from 'styled-components/macro'

import Game from './components/game'
import damaApp from './reducers'

const ScaledContent = styled.div`
  position: relative;
  width: calc(80vh - 80px);
  min-width: 460px;
  max-width: 95vw;
  margin: 0 auto;
`

const App = () => {
  return (
    <DndProvider backend={TouchBackend} options={{ enableMouseEvents: true }}>
      <ScaledContent>
        <Game />
      </ScaledContent>
    </DndProvider>
  )
}

const middlewares = []

if (process.env.NODE_ENV === 'development') {
  middlewares.push(logger)
}

export const appState = createStore(damaApp, applyMiddleware(...middlewares))

const GlobalStyle = createGlobalStyle`
  html {
    position: relative;
    min-height: 100%;
  }

  body {
    background-color: cornsilk;
    min-width: 420px;
    padding: 1%;
    margin: 0px;
  }

  .welcome-dlg {
    max-width: 50% !important;
  }
`

ReactDOM.render(
  <React.StrictMode>
    <Provider store={appState}>
      <App />
    </Provider>
    <GlobalStyle />
  </React.StrictMode>,
  document.getElementById('root')
)
<commit_msg>use configure store, there is one issue now, that we will take care of later.<commit_after>import 'bootstrap/dist/css/bootstrap.min.css'

import React from 'react'
import ReactDOM from 'react-dom'
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
import { logger } from 'redux-logger'
import { Provider } from 'react-redux'
import { TouchBackend } from 'react-dnd-touch-backend'
import { DndProvider } from 'react-dnd'
import styled, { createGlobalStyle } from 'styled-components/macro'

import Game from './components/game'
import reducer from './reducers'

const ScaledContent = styled.div`
  position: relative;
  width: calc(80vh - 80px);
  min-width: 460px;
  max-width: 95vw;
  margin: 0 auto;
`

const App = () => {
  return (
    <DndProvider backend={TouchBackend} options={{ enableMouseEvents: true }}>
      <ScaledContent>
        <Game />
      </ScaledContent>
    </DndProvider>
  )
}

const middleware = [...getDefaultMiddleware()]

if (process.env.NODE_ENV === 'development') {
  middleware.push(logger)
}

export const appState = configureStore({
  reducer,
  middleware,
  devTools: process.env.NODE_ENV !== 'production'
})

const GlobalStyle = createGlobalStyle`
  html {
    position: relative;
    min-height: 100%;
  }

  body {
    background-color: cornsilk;
    min-width: 420px;
    padding: 1%;
    margin: 0px;
  }

  .welcome-dlg {
    max-width: 50% !important;
  }
`

ReactDOM.render(
  <React.StrictMode>
    <Provider store={appState}>
      <App />
    </Provider>
    <GlobalStyle />
  </React.StrictMode>,
  document.getElementById('root')
)
<|endoftext|>


<commit_before>'use strict'

const debug_ = require('debug');

const debug = debug_('purs-loader');

const debugVerbose = debug_('purs-loader:verbose');

const loaderUtils = require('loader-utils')

const Promise = require('bluebird')

const path = require('path')

const PsModuleMap = require('./purs-module-map');

const compile = require('./compile');

const bundle = require('./bundle');

const ide = require('./ide');

const toJavaScript = require('./to-javascript');

const sourceMaps = require('./source-maps');

const spawn = require('cross-spawn').sync

const eol = require('os').EOL

var CACHE_VAR = {
  rebuild: false,
  deferred: [],
  bundleModules: [],
  ideServer: null,
  psModuleMap: null,
  warnings: [],
  errors: [],
  compilationStarted: false,
  compilationFinished: false,
  installed: false,
  srcOption: []
};

module.exports = function purescriptLoader(source, map) {
  this.cacheable && this.cacheable();

  const webpackContext = (this.options && this.options.context) || this.rootContext;

  const callback = this.async();

  const loaderOptions = loaderUtils.getOptions(this) || {};

  const srcOption = (pscPackage => {
    const srcPath = path.join('src', '**', '*.purs');

    const bowerPath = path.join('bower_components', 'purescript-*', 'src', '**', '*.purs');

    if (CACHE_VAR.srcOption.length > 0) {
      return CACHE_VAR.srcOption;
    }
    else if (pscPackage) {
      const pscPackageCommand = 'psc-package';

      const pscPackageArgs = ['sources'];

      const loaderSrc = loaderOptions.src || [
        srcPath
      ];

      debug('psc-package %s %o', pscPackageCommand, pscPackageArgs);

      const cmd = spawn(pscPackageCommand, pscPackageArgs);

      if (cmd.error) {
        throw new Error(cmd.error);
      }
      else if (cmd.status !== 0) {
        const error = cmd.stdout.toString();

        throw new Error(error);
      }
      else {
        const result = cmd.stdout.toString().split(eol).filter(v => v != '').concat(loaderSrc);

        debug('psc-package result: %o', result);

        CACHE_VAR.srcOption = result;

        return result;
      }
    }
    else {
      const result = loaderOptions.src || [
        bowerPath,
        srcPath
      ];

      CACHE_VAR.srcOption = result;

      return result;
    }
  })(loaderOptions.pscPackage);

  const options = Object.assign({
    context: webpackContext,
    psc: null,
    pscArgs: {},
    pscBundle: null,
    pscBundleArgs: {},
    pscIdeClient: null,
    pscIdeClientArgs: {},
    pscIdeServer: null,
    pscIdeServerArgs: {},
    pscIdeRebuildArgs: {},
    pscIde: false,
    pscIdeColors: loaderOptions.psc === 'psa',
    pscPackage: false,
    bundleOutput: 'output/bundle.js',
    bundleNamespace: 'PS',
    bundle: false,
    warnings: true,
    watch: false,
    output: 'output',
    src: []
  }, loaderOptions, {
    src: srcOption
  });

  if (!CACHE_VAR.installed) {
    debugVerbose('installing purs-loader with options: %O', options);

    CACHE_VAR.installed = true;

    // invalidate loader CACHE_VAR when bundle is marked as invalid (in watch mode)
    this._compiler.plugin('invalid', () => {
      debugVerbose('invalidating loader CACHE_VAR');

      CACHE_VAR = {
        rebuild: options.pscIde,
        deferred: [],
        bundleModules: [],
        ideServer: CACHE_VAR.ideServer,
        psModuleMap: CACHE_VAR.psModuleMap,
        warnings: [],
        errors: [],
        compilationStarted: false,
        compilationFinished: false,
        installed: CACHE_VAR.installed,
        srcOption: []
      };
    });

    // add psc warnings to webpack compilation warnings
    this._compiler.plugin('after-compile', (compilation, callback) => {
      CACHE_VAR.warnings.forEach(warning => {
        compilation.warnings.push(warning);
      });

      CACHE_VAR.errors.forEach(error => {
        compilation.errors.push(error);
      });

      callback()
    });
  }

  const psModuleName = PsModuleMap.matchModule(source);

  const psModule = {
    name: psModuleName,
    source: source,
    load: ({js, map}) => callback(null, js, map),
    reject: error => callback(error),
    srcPath: this.resourcePath,
    remainingRequest: loaderUtils.getRemainingRequest(this),
    srcDir: path.dirname(this.resourcePath),
    jsPath: path.resolve(path.join(options.output, psModuleName, 'index.js')),
    options: options,
    cache: CACHE_VAR,
    emitWarning: warning => {
      if (options.warnings && warning.length) {
        CACHE_VAR.warnings.push(warning);
      }
    },
    emitError: error => {
      if (error.length) {
        CACHE_VAR.errors.push(error);
      }
    }
  }

  debug('loading %s', psModule.name);

  if (options.bundle) {
    CACHE_VAR.bundleModules.push(psModule.name);
  }

  if (CACHE_VAR.rebuild) {
    const connect = () => {
      if (!CACHE_VAR.ideServer) {
        CACHE_VAR.ideServer = true;

        return ide.connect(psModule)
          .then(ideServer => {
            CACHE_VAR.ideServer = ideServer;
            return psModule;
          })
          .then(ide.loadWithRetry)
          .catch(error => {
            if (CACHE_VAR.ideServer.kill) {
              debug('ide failed to initially load modules, stopping the ide server process');

              CACHE_VAR.ideServer.kill();
            }

            CACHE_VAR.ideServer = null;

            return Promise.reject(error);
          })
        ;
      }
      else {
        return Promise.resolve(psModule);
      }
    };

    const rebuild = () =>
      ide.rebuild(psModule)
      .then(() =>
        toJavaScript(psModule)
          .then(js => sourceMaps(psModule, js))
          .then(psModule.load)
          .catch(psModule.reject)
      )
      .catch(error => {
        if (error instanceof ide.UnknownModuleError) {
          // Store the modules that trigger a recompile due to an
          // unknown module error. We need to wait until compilation is
          // done before loading these files.

          CACHE_VAR.deferred.push(psModule);

          if (!CACHE_VAR.compilationStarted) {
            CACHE_VAR.compilationStarted = true;

            return compile(psModule)
              .then(() => {
                CACHE_VAR.compilationFinished = true;
              })
              .then(() =>
                Promise.map(CACHE_VAR.deferred, psModule =>
                  ide.load(psModule)
                    .then(() => toJavaScript(psModule))
                    .then(js => sourceMaps(psModule, js))
                    .then(psModule.load)
                )
              )
              .catch(error => {
                CACHE_VAR.deferred[0].reject(error);

                CACHE_VAR.deferred.slice(1).forEach(psModule => {
                  psModule.reject(new Error('purs-loader failed'));
                })
              })
            ;
          }
          else {
            // The compilation has started. We must wait until it is
            // done in order to ensure the module map contains all of
            // the unknown modules.
          }
        }
        else {
          debug('ide rebuild failed due to an unhandled error: %o', error);

          psModule.reject(error);
        }
      })
    ;

    connect().then(rebuild);
  }
  else if (CACHE_VAR.compilationFinished) {
    debugVerbose('compilation is already finished, loading module %s', psModule.name);

    toJavaScript(psModule)
      .then(js => sourceMaps(psModule, js))
      .then(psModule.load)
      .catch(psModule.reject);
  }
  else {
    // The compilation has not finished yet. We need to wait for
    // compilation to finish before the loaders run so that references
    // to compiled output are valid. Push the modules into the CACHE_VAR to
    // be loaded once the complation is complete.

    CACHE_VAR.deferred.push(psModule);

    if (!CACHE_VAR.compilationStarted) {
      CACHE_VAR.compilationStarted = true;

      compile(psModule)
        .then(() => {
          CACHE_VAR.compilationFinished = true;
        })
        .then(() => {
          if (options.bundle) {
            return bundle(options, CACHE_VAR.bundleModules);
          }
        })
        .then(() =>
          Promise.map(CACHE_VAR.deferred, psModule =>
            toJavaScript(psModule)
              .then(js => sourceMaps(psModule, js))
              .then(psModule.load)
          )
        )
        .catch(error => {
          CACHE_VAR.deferred[0].reject(error);

          CACHE_VAR.deferred.slice(1).forEach(psModule => {
            psModule.reject(new Error('purs-loader failed'));
          })
        })
      ;
    }
    else {
      // The complation has started. Nothing to do but wait until it is
      // done before loading all of the modules.
    }
  }
}
<commit_msg>Added hooks support (#122)<commit_after>'use strict'

const debug_ = require('debug');

const debug = debug_('purs-loader');

const debugVerbose = debug_('purs-loader:verbose');

const loaderUtils = require('loader-utils')

const Promise = require('bluebird')

const path = require('path')

const PsModuleMap = require('./purs-module-map');

const compile = require('./compile');

const bundle = require('./bundle');

const ide = require('./ide');

const toJavaScript = require('./to-javascript');

const sourceMaps = require('./source-maps');

const spawn = require('cross-spawn').sync

const eol = require('os').EOL

var CACHE_VAR = {
  rebuild: false,
  deferred: [],
  bundleModules: [],
  ideServer: null,
  psModuleMap: null,
  warnings: [],
  errors: [],
  compilationStarted: false,
  compilationFinished: false,
  installed: false,
  srcOption: []
};

module.exports = function purescriptLoader(source, map) {
  this.cacheable && this.cacheable();

  const webpackContext = (this.options && this.options.context) || this.rootContext;

  const callback = this.async();

  const loaderOptions = loaderUtils.getOptions(this) || {};

  const srcOption = (pscPackage => {
    const srcPath = path.join('src', '**', '*.purs');

    const bowerPath = path.join('bower_components', 'purescript-*', 'src', '**', '*.purs');

    if (CACHE_VAR.srcOption.length > 0) {
      return CACHE_VAR.srcOption;
    }
    else if (pscPackage) {
      const pscPackageCommand = 'psc-package';

      const pscPackageArgs = ['sources'];

      const loaderSrc = loaderOptions.src || [
        srcPath
      ];

      debug('psc-package %s %o', pscPackageCommand, pscPackageArgs);

      const cmd = spawn(pscPackageCommand, pscPackageArgs);

      if (cmd.error) {
        throw new Error(cmd.error);
      }
      else if (cmd.status !== 0) {
        const error = cmd.stdout.toString();

        throw new Error(error);
      }
      else {
        const result = cmd.stdout.toString().split(eol).filter(v => v != '').concat(loaderSrc);

        debug('psc-package result: %o', result);

        CACHE_VAR.srcOption = result;

        return result;
      }
    }
    else {
      const result = loaderOptions.src || [
        bowerPath,
        srcPath
      ];

      CACHE_VAR.srcOption = result;

      return result;
    }
  })(loaderOptions.pscPackage);

  const options = Object.assign({
    context: webpackContext,
    psc: null,
    pscArgs: {},
    pscBundle: null,
    pscBundleArgs: {},
    pscIdeClient: null,
    pscIdeClientArgs: {},
    pscIdeServer: null,
    pscIdeServerArgs: {},
    pscIdeRebuildArgs: {},
    pscIde: false,
    pscIdeColors: loaderOptions.psc === 'psa',
    pscPackage: false,
    bundleOutput: 'output/bundle.js',
    bundleNamespace: 'PS',
    bundle: false,
    warnings: true,
    watch: false,
    output: 'output',
    src: []
  }, loaderOptions, {
    src: srcOption
  });

  if (!CACHE_VAR.installed) {
    debugVerbose('installing purs-loader with options: %O', options);

    CACHE_VAR.installed = true;

    const invalidCb = () => {
      debugVerbose('invalidating loader CACHE_VAR');

      CACHE_VAR = {
        rebuild: options.pscIde,
        deferred: [],
        bundleModules: [],
        ideServer: CACHE_VAR.ideServer,
        psModuleMap: CACHE_VAR.psModuleMap,
        warnings: [],
        errors: [],
        compilationStarted: false,
        compilationFinished: false,
        installed: CACHE_VAR.installed,
        srcOption: []
      };
    }

    // invalidate loader CACHE_VAR when bundle is marked as invalid (in watch mode)
    if(this._compiler.hooks){
      this._compiler.hooks.invalid.tap('purs-loader', invalidCb);
    } else {
      this._compiler.plugin('invalid', invalidCb);
    }

    const afterCompileCb = (compilation, callback) => {
      CACHE_VAR.warnings.forEach(warning => {
        compilation.warnings.push(warning);
      });

      CACHE_VAR.errors.forEach(error => {
        compilation.errors.push(error);
      });

      callback()
    }

    // add psc warnings to webpack compilation warnings
    if(this._compiler.hooks) {
      this._compiler.hooks.afterCompile.tapAsync('purs-loader', afterCompileCb);
    } else {
      this._compiler.plugin('after-compile', afterCompileCb);
    }
  }

  const psModuleName = PsModuleMap.matchModule(source);

  const psModule = {
    name: psModuleName,
    source: source,
    load: ({js, map}) => callback(null, js, map),
    reject: error => callback(error),
    srcPath: this.resourcePath,
    remainingRequest: loaderUtils.getRemainingRequest(this),
    srcDir: path.dirname(this.resourcePath),
    jsPath: path.resolve(path.join(options.output, psModuleName, 'index.js')),
    options: options,
    cache: CACHE_VAR,
    emitWarning: warning => {
      if (options.warnings && warning.length) {
        CACHE_VAR.warnings.push(warning);
      }
    },
    emitError: error => {
      if (error.length) {
        CACHE_VAR.errors.push(error);
      }
    }
  }

  debug('loading %s', psModule.name);

  if (options.bundle) {
    CACHE_VAR.bundleModules.push(psModule.name);
  }

  if (CACHE_VAR.rebuild) {
    const connect = () => {
      if (!CACHE_VAR.ideServer) {
        CACHE_VAR.ideServer = true;

        return ide.connect(psModule)
          .then(ideServer => {
            CACHE_VAR.ideServer = ideServer;
            return psModule;
          })
          .then(ide.loadWithRetry)
          .catch(error => {
            if (CACHE_VAR.ideServer.kill) {
              debug('ide failed to initially load modules, stopping the ide server process');

              CACHE_VAR.ideServer.kill();
            }

            CACHE_VAR.ideServer = null;

            return Promise.reject(error);
          })
        ;
      }
      else {
        return Promise.resolve(psModule);
      }
    };

    const rebuild = () =>
      ide.rebuild(psModule)
      .then(() =>
        toJavaScript(psModule)
          .then(js => sourceMaps(psModule, js))
          .then(psModule.load)
          .catch(psModule.reject)
      )
      .catch(error => {
        if (error instanceof ide.UnknownModuleError) {
          // Store the modules that trigger a recompile due to an
          // unknown module error. We need to wait until compilation is
          // done before loading these files.

          CACHE_VAR.deferred.push(psModule);

          if (!CACHE_VAR.compilationStarted) {
            CACHE_VAR.compilationStarted = true;

            return compile(psModule)
              .then(() => {
                CACHE_VAR.compilationFinished = true;
              })
              .then(() =>
                Promise.map(CACHE_VAR.deferred, psModule =>
                  ide.load(psModule)
                    .then(() => toJavaScript(psModule))
                    .then(js => sourceMaps(psModule, js))
                    .then(psModule.load)
                )
              )
              .catch(error => {
                CACHE_VAR.deferred[0].reject(error);

                CACHE_VAR.deferred.slice(1).forEach(psModule => {
                  psModule.reject(new Error('purs-loader failed'));
                })
              })
            ;
          }
          else {
            // The compilation has started. We must wait until it is
            // done in order to ensure the module map contains all of
            // the unknown modules.
          }
        }
        else {
          debug('ide rebuild failed due to an unhandled error: %o', error);

          psModule.reject(error);
        }
      })
    ;

    connect().then(rebuild);
  }
  else if (CACHE_VAR.compilationFinished) {
    debugVerbose('compilation is already finished, loading module %s', psModule.name);

    toJavaScript(psModule)
      .then(js => sourceMaps(psModule, js))
      .then(psModule.load)
      .catch(psModule.reject);
  }
  else {
    // The compilation has not finished yet. We need to wait for
    // compilation to finish before the loaders run so that references
    // to compiled output are valid. Push the modules into the CACHE_VAR to
    // be loaded once the complation is complete.

    CACHE_VAR.deferred.push(psModule);

    if (!CACHE_VAR.compilationStarted) {
      CACHE_VAR.compilationStarted = true;

      compile(psModule)
        .then(() => {
          CACHE_VAR.compilationFinished = true;
        })
        .then(() => {
          if (options.bundle) {
            return bundle(options, CACHE_VAR.bundleModules);
          }
        })
        .then(() =>
          Promise.map(CACHE_VAR.deferred, psModule =>
            toJavaScript(psModule)
              .then(js => sourceMaps(psModule, js))
              .then(psModule.load)
          )
        )
        .catch(error => {
          CACHE_VAR.deferred[0].reject(error);

          CACHE_VAR.deferred.slice(1).forEach(psModule => {
            psModule.reject(new Error('purs-loader failed'));
          })
        })
      ;
    }
    else {
      // The complation has started. Nothing to do but wait until it is
      // done before loading all of the modules.
    }
  }
}
<|endoftext|>


<commit_before>const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
app.use(bodyParser.urlencoded({ extended: true }));
const HashMap = require('hashmap');
const dirname = fs.realpathSync('./');
const timeoutInMS = 28800000;

var teams = new HashMap();
var ingredients = JSON.parse(fs.readFileSync(__dirname + '/data/ingredients.json', 'utf8'));
var team_suggestions = new HashMap();

// build api endpoint for getting js files
fs.readdirSync(dirname + '/src/js').forEach(file => {
    app.get('/js/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/src/js/' + file);
    });
});

// build api endpoint for getting bootstrap files
fs.readdirSync(dirname + '/node_modules/bootstrap/dist/css').forEach(file => {
    app.get('/css/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/node_modules/bootstrap/dist/css/' + file);
    });
});

app.get('/', function (req, res) {
    res.status(200).sendFile(__dirname + "/index.htm");
});

app.get('/teams', function (req, res) {
    res.status(200).sendFile(__dirname + "/teamPage.html");
});

app.get('/pizzas/amount', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        let amount = {
            amount: teams.get(teamname).pizza_count
        };
        res.status(200).end(JSON.stringify(amount));
    } else {
        res.sendStatus(400);
    }
});

app.get('/pizzas/ingredients', function (req, res) {
    if (ingredients.length > 0) {
        res.status(200).end(JSON.stringify(ingredients));
    } else {
        res.sendStatus(404);
    }
});

app.get('/pizzas/suggestions', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && team_suggestions.has(teamname)) {
        let suggestions = team_suggestions.get(teamname);
        res.status(200).end(JSON.stringify(suggestions));
    } else {
        res.sendStatus(400);
    }
});

app.get('/pizzas/suggest', function (req, res) {
    res.status(200).sendFile(__dirname + '/proposer.html');
});

app.get('/teams/data', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        res.status(200).end(JSON.stringify(teams.get(teamname)));
    } else {
        res.sendStatus(400);
    }
});

app.post('/teams/create', function (req, res) {
    let teamname = req.body.teamname;
    if (teamname != undefined && !teams.has(teamname) && !team_suggestions.has(teamname)) {
        console.log('Creating team ' + teamname);
        let data = {
            teamsize: {
                number: 0,
                type: null
            },
            pizza_count: 0
        };
        teams.set(teamname, data);
        team_suggestions.set(teamname, []);
        setTimeout(callback => {
            teams.remove(teamname);
            team_suggestions.remove(teamname);
        }, timeoutInMS);
        res.status(200).sendFile(__dirname + '/js/teamPage.js');
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname }));
    } else {
        console.log('Creating Team: Failure because of undefined teamname!');
        res.sendStatus(400);
    }
});

app.post('/teams/teamsize', function (req, res) {
    let count = parseInt(req.body.count);
    let type = req.body.type;
    let teamname = req.body.teamname;
    if (count != NaN && type != undefined && teamname != undefined) {
        console.log('Update team size for team ' + teamname);
        let pizza_count = computeNumberOfPizzas(count, type);
        let data = {
            teamsize: {
                number: count,
                type: type
            },
            pizza_count: pizza_count
        };
        console.log(data);
        teams.set(teamname, data);
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname, data: data }));
    } else {
        console.log('Update team size failed');
        res.sendStatus(400);
    }
});

app.post('/pizzas/suggestions', function (req, res) {
    let teamname = req.body.teamname;
    let ingredients = req.body.ingredients;
    if (teamname != undefined && ingredients.length > 0 && team_suggestions.has(teamname)) {
        console.log('Add suggestion for team ' + teamname);
        let suggestion = {
            id: team_suggestions.get(teamname).length,
            ingredients: ingredients,
            vote: 0
        };
        team_suggestions.get(teamname).push(suggestion);
        res.end(JSON.stringify(suggestion));
    } else {
        console.log('Failed to add suggestion');
        res.sendStatus(400);
    }
});

app.post('/pizzas/suggestions/vote', function (req, res) {
    let teamname = req.body.teamname;
    let suggestion_id = parseInt(req.body.id);
    let vote = parseInt(req.body.vote);
    if (teamname != undefined && suggestion_id != NaN && vote != NaN && team_suggestions.has(teamname)) {
        console.log('Update vote vor suggestion');
        vote = Math.sign(vote);
        team_suggestions.get(teamname)[suggestion_id].vote += vote;
        res.sendStatus(200);
    } else {
        console.log('Update voting failed');
        res.sendStatus(400);
    }
});

function computeNumberOfPizzas(count, type) {
    if (type == 'Personen') {
        let number = count * 4;
        return Math.ceil(number / 16);
    } else if (type == 'Pizzastuecke') {
        return Math.ceil(count / 16);
    } else {
        return 0;
    }
};

function saveToFile(data, filename = "tfmap.log", exitOnWrite = false) {
    let folderName = "results";
    if (!fs.existsSync(folderName)) {
        fs.mkdirSync(folderName);
    }
    fs.writeFileSync('results/' + filename, data);
    console.log("The file was saved!");
    if (exitOnWrite) {
        process.exit(0);
    }
}

var server = app.listen(8081, function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log("REST server listening at http://%s:%s", host, port);
});<commit_msg>Change failure status codes to 302 with redirect to main page. Status code 400 on /teams/create changed to 420.<commit_after>const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
app.use(bodyParser.urlencoded({ extended: true }));
const HashMap = require('hashmap');
const dirname = fs.realpathSync('./');
const timeoutInMS = 28800000;

var teams = new HashMap();
var ingredients = JSON.parse(fs.readFileSync(__dirname + '/data/ingredients.json', 'utf8'));
var team_suggestions = new HashMap();

// build api endpoint for getting js files
fs.readdirSync(dirname + '/src/js').forEach(file => {
    app.get('/js/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/src/js/' + file);
    });
});

// build api endpoint for getting bootstrap files
fs.readdirSync(dirname + '/node_modules/bootstrap/dist/css').forEach(file => {
    app.get('/css/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/node_modules/bootstrap/dist/css/' + file);
    });
});

app.get('/', function (req, res) {
    res.status(200).sendFile(__dirname + "/index.htm");
});

app.get('/teams', function (req, res) {
    res.status(200).sendFile(__dirname + "/teamPage.html");
});

app.get('/pizzas/amount', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        let amount = {
            amount: teams.get(teamname).pizza_count
        };
        res.status(200).end(JSON.stringify(amount));
    } else {
        res.redirect(303, '/');
    }
});

app.get('/pizzas/ingredients', function (req, res) {
    if (ingredients.length > 0) {
        res.status(200).end(JSON.stringify(ingredients));
    } else {
        res.redirect(303, '/');
    }
});

app.get('/pizzas/suggestions', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && team_suggestions.has(teamname)) {
        let suggestions = team_suggestions.get(teamname);
        res.status(200).end(JSON.stringify(suggestions));
    } else {
        res.redirect(303, '/');
    }
});

app.get('/pizzas/suggest', function (req, res) {
    res.status(200).sendFile(__dirname + '/proposer.html');
});

app.get('/teams/data', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        res.status(200).end(JSON.stringify(teams.get(teamname)));
    } else {
        res.redirect(303, '/');
    }
});

app.post('/teams/create', function (req, res) {
    let teamname = req.body.teamname;
    if (teamname != undefined && !teams.has(teamname) && !team_suggestions.has(teamname)) {
        console.log('Creating team ' + teamname);
        let data = {
            teamsize: {
                number: 0,
                type: null
            },
            pizza_count: 0
        };
        teams.set(teamname, data);
        team_suggestions.set(teamname, []);
        setTimeout(callback => {
            teams.remove(teamname);
            team_suggestions.remove(teamname);
        }, timeoutInMS);
        res.status(200).sendFile(__dirname + '/js/teamPage.js');
        res.redirect(303, '/teams/?teamname=' + teamname);
    } else {
        console.log('Creating Team: Failure because of undefined teamname!');
        res.sendStatus(420);
    }
});

app.post('/teams/teamsize', function (req, res) {
    let count = parseInt(req.body.count);
    let type = req.body.type;
    let teamname = req.body.teamname;
    if (count != NaN && type != undefined && teamname != undefined) {
        console.log('Update team size for team ' + teamname);
        let pizza_count = computeNumberOfPizzas(count, type);
        let data = {
            teamsize: {
                number: count,
                type: type
            },
            pizza_count: pizza_count
        };
        console.log(data);
        teams.set(teamname, data);
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname, data: data }));
    } else {
        console.log('Update team size failed');
        res.redirect(303, '/');
    }
});

app.post('/pizzas/suggestions', function (req, res) {
    let teamname = req.body.teamname;
    let ingredients = req.body.ingredients;
    if (teamname != undefined && ingredients.length > 0 && team_suggestions.has(teamname)) {
        console.log('Add suggestion for team ' + teamname);
        let suggestion = {
            id: team_suggestions.get(teamname).length,
            ingredients: ingredients,
            vote: 0
        };
        team_suggestions.get(teamname).push(suggestion);
        res.end(JSON.stringify(suggestion));
    } else {
        console.log('Failed to add suggestion');
        res.redirect(303, '/');
    }
});

app.post('/pizzas/suggestions/vote', function (req, res) {
    let teamname = req.body.teamname;
    let suggestion_id = parseInt(req.body.id);
    let vote = parseInt(req.body.vote);
    if (teamname != undefined && suggestion_id != NaN && vote != NaN && team_suggestions.has(teamname)) {
        console.log('Update vote vor suggestion');
        vote = Math.sign(vote);
        team_suggestions.get(teamname)[suggestion_id].vote += vote;
        res.sendStatus(200);
    } else {
        console.log('Update voting failed');
        res.redirect(303, '/');
    }
});

function computeNumberOfPizzas(count, type) {
    if (type == 'Personen') {
        let number = count * 4;
        return Math.ceil(number / 16);
    } else if (type == 'Pizzastuecke') {
        return Math.ceil(count / 16);
    } else {
        return 0;
    }
};

function saveToFile(data, filename = "tfmap.log", exitOnWrite = false) {
    let folderName = "results";
    if (!fs.existsSync(folderName)) {
        fs.mkdirSync(folderName);
    }
    fs.writeFileSync('results/' + filename, data);
    console.log("The file was saved!");
    if (exitOnWrite) {
        process.exit(0);
    }
}

var server = app.listen(8081, function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log("REST server listening at http://%s:%s", host, port);
});<|endoftext|>


<commit_before>// core modules
var path = require('path'),
    fs = require('fs');
// dep modules
var _ = require('lodash'),
    Promise = require('bluebird'),
    glob = require('glob');
// own modules
var helper = require('./lib/helper'),
    utils = require('./lib/utils');

module.exports = (function () {

    var jsdocx = {};
    glob = Promise.promisify(glob);

    // if the dependent project has jsdoc dependency, ours will not be
    // installed. and since we don't use the jsdoc module via require but a
    // specific file (jsdoc.js), we cannot be sure of its location. this method
    // will try to find it if exists.
    var jsdocjs = 'jsdoc/jsdoc.js';
    try {
        var local = path.join('..', 'node_modules', jsdocjs);
        if (fs.existsSync(local)) {
            jsdocx.path = local;
        } else {
            // Use the internal require() machinery to look up the location
            // of a module, but rather than loading the module, just return
            // the resolved filename.
            jsdocx.path = require.resolve(jsdocjs);
            // jsdoc module does not expose a main file. so instead of
            // require.resolve('jsdoc') - which will fail; we'll look for
            // 'jsdoc/jsdoc.js'.

            // for example, if the parent project has it, we'll get:
            // /path/to/parent-project/node_modules/jsdoc/jsdoc.js
        }
    } catch (e) {
        throw new Error('Could not find jsdoc module.');
    }

    // ---------------------------
    // HELPERS
    // ---------------------------

    function identity(o) {
        return o;
    }

    // http://usejsdoc.org/about-commandline.html
    // http://usejsdoc.org/about-configuring-jsdoc.html
    function buildArgs(options) {
        // access, private, readme, template, etc.. These CLI options do not
        // have affect when run with --explain (-X) flag. They are for
        // jsdoc-genrated docs. access is handled within the filter method.
        var opts = _.defaults(options, {
            // files: ... // non-jsdoc option
            encoding: 'utf8',
            package: null, // path
            recurse: false,
            pedantic: false,
            query: null
            // debug: false
            // verbose: false
        });

        var args = ['-X'];
        args = args.concat(helper.ensureArray(opts.files));
        args.push('-e', opts.encoding);
        if (_.isString(opts.package)) {
            args.push('-P', opts.package);
        }
        if (opts.recurse) args.push('-r');
        if (opts.pedantic) args.push('--pedantic');
        if (opts.query) args.push('-q', opts.query);
        // if (opts.debug) args.push('--debug');
        // if (opts.verbose) args.push('--verbose');
        return args;
    }

    // Builds the configuration object for JSDoc. JSDoc takes a filepath for
    // configuration (-c command). So we need to create a temp JSON file. This
    // function creates the conf object to be written to that temp file before
    // passing to jsdoc as a command line argument.
    function buildConf(options) {
        var opts = options || {};

        // updating default JSDoc configuration.
        // see http://usejsdoc.org/about-configuring-jsdoc.html
        return {
            tags: {
                allowUnknownTags: typeof opts.allowUnknownTags === 'boolean'
                    ? opts.allowUnknownTags
                    : true,
                dictionaries: !Array.isArray(opts.dictionaries)
                    ? ['jsdoc', 'closure']
                    : opts.dictionaries
            },
            source: {
                includePattern: opts.includePattern || '.+\\.js(doc|x)?$',
                excludePattern: opts.excludePattern || '(^|\\/|\\\\)_'
            },
            plugins: !Array.isArray(opts.plugins) ? [] : opts.plugins,
            templates: {
                cleverLinks: false,
                monospaceLinks: false
            }
        };
    }

    function relativePath(symbol, rPath) {
        if (!symbol || !rPath) return;
        var p = symbol.meta && helper.getStr(symbol.meta.path);
        if (p) {
            symbol.meta.path = helper.normalizePath(path.relative(p, rPath));
        }
    }

    function normalizeAccess(access) {
        // ['public', 'protected', 'private'];
        if (access === 'all') return access; // all
        if (!_.isString(access) && !_.isArray(access)) {
            return ['public', 'protected'];
        }
        return helper.ensureArray(access);
    }

    // if group'ed, symbols are sorted with operators (#.~:) intact. Otherwise
    // operators are not taken into account.
    function getSorter(sortType, prop) {
        prop = prop || '$longname';
        var re = /[#.~:]/g,
            group = sortType === 'grouped';
        return function symbolSorter(a, b) {
            var A = group ? a[prop] : a[prop].replace(re, '_'),
                B = group ? b[prop] : b[prop].replace(re, '_');
            var result = A.toLocaleUpperCase().localeCompare(B.toLocaleUpperCase());
            // console.log('comparing:', A, '<<—>>', B, '==>', result);
            return result;
        };
    }

    // sorts documentation symbols and properties of each symbol, if any.
    function sortDocs(docs, sortType) {
        var sorter = getSorter(sortType, '$longname'),
            propSorter = getSorter(sortType, 'name');
        docs.sort(sorter);
        docs.forEach(function (symbol) {
            if (symbol && Array.isArray(symbol.properties)) {
                symbol.properties.sort(propSorter);
            }
        });
    }

    function hierarchy(docs, sortType) {
        var parent,
            sorter = sortType ? getSorter(sortType) : null,
            propSorter = sortType ? getSorter(sortType, 'name') : null;
        _.eachRight(docs, function (symbol, index) {
            // Move constructor (method definition) to class declaration symbol
            if (utils.isConstructor(symbol)) {
                parent = _.find(docs, function (o) {
                    return o.longname === symbol.longname && utils.isClass(o);
                });
                if (parent) {
                    parent.$constructor = symbol;
                    docs.splice(index, 1);
                }
            // otherwise, move symbols with memberof property to corresponding parent member.
            } else if (symbol.memberof) {
                // first check and sort if it has properties
                if (propSorter && Array.isArray(symbol.properties)) {
                    symbol.properties.sort(propSorter);
                }

                parent = _.find(docs, { longname: symbol.memberof });
                if (parent) {
                    parent.$members = parent.$members || [];
                    parent.$members.push(symbol);
                    if (sorter) {
                        parent.$members.sort(sorter);
                    } else {
                        // reverse bec. we used eachRight
                        parent.$members.reverse();
                    }
                    docs.splice(index, 1);
                }
            }
        });
        if (sorter) docs.sort(sorter);
        return docs;
    }

    function promiseGlobFiles(globs) {
        globs = helper.ensureArray(globs);
        return Promise.reduce(globs, function (memo, pattern) {
            return glob(pattern).then(function (paths) {
                return memo.concat(paths);
            });
        }, []);
    }

    // ---------------------------
    // PUBLIC METHODS
    // ---------------------------

    /**
     *  Filters the parsed documentation output array.
     *
     *  @param {Array} docs - Documentation output array.
     *  @param {Object} [options] - Filter options.
     *  @param {Function} [predicate] - The function invoked per iteration.
     *  Returning a falsy value will remove the symbol from the output.
     *  Returning true will keep the original symbol. To keep the symbol and
     *  alter its contents, simply return an altered symbol object.
     *
     *  @returns {Array} - Filtered documentation array.
     */
    jsdocx.filter = function (docs, options, predicate) {
        if (!options && !predicate) return docs;
        if (_.isFunction(options)) {
            predicate = options;
            options = {};
        }
        if (!_.isFunction(predicate)) predicate = identity;
        docs = helper.ensureArray(docs);

        options = _.defaults(options, {
            access: undefined,
            package: true,
            module: true,
            undocumented: true,
            undescribed: true,
            hierarchy: false,
            sort: false, // (true|"alphabetic")|"grouped"|false
            relativePath: null
        });

        var access = normalizeAccess(options.access);
        var isCon, undoc, undesc, pkg, mdl, acc, o;
        docs = _.reduce(docs, function (memo, symbol) {
            // console.log(symbol.longname, symbol.kind, symbol.access, symbol.meta ? symbol.meta.code.type : '');

            // JSDoc overwrites the `longname` and `name` of the symbol, if it
            // has an alias. See https://github.com/jsdoc3/jsdoc/issues/1217 and
            // documentation of jsdocx.utils.getFullName()
            symbol.$longname = utils.getLongName(symbol);

            undoc = options.undocumented || symbol.undocumented !== true;
            undesc = options.undescribed || utils.hasDescription(symbol);
            pkg = options.package || symbol.kind !== 'package';
            mdl = options.module || symbol.longname !== 'module.exports';
            // access might not be explicitly set for the symbol.
            // in this case, we'll include the symbol.
            acc = access === 'all' || !symbol.access || access.indexOf(symbol.access) >= 0;
            // constructor symbol is undocumented=true even if it's documented
            isCon = acc && utils.isConstructor(symbol);
            if (isCon || (undoc && undesc && pkg && mdl && acc)) {
                relativePath(symbol, options.relativePath);
                o = predicate(symbol);
                if (_.isPlainObject(o)) {
                    memo.push(o); // filtered symbol pushed
                } else if (o) { // boolean check
                    memo.push(symbol); // original symbol pushed
                }
            }
            return memo;
        }, []);

        if (options.hierarchy) {
            docs = hierarchy(docs, options.sort);
        } else if (options.sort) {
            // var sorter = getSorter(options.sort);
            // docs.sort(sorter);
            sortDocs(docs, options.sort);
        }
        return docs;
    };

    /**
     * Executes the `jsdoc` command and parses the output into a Javascript
     * object/array; with the specified options.
     *
     * @param {Object|String|Array} options - Either an options object or one
     * or more source files to be processed.
     * @param {Function} [callback] - Callback function to be executed
     * in the following signature: function (err, array) { ... }`
     * Omit this callback to return a `Promise`.
     *
     * @returns {void|Promise} - Returns a `Promise` if `callback` is omitted.
     */
    jsdocx.parse = function (options, callback) {
        if (!options) throw new Error(helper.ERR.SOURCE);
        var opts = !_.isPlainObject(options)
            ? { files: options }
            : options;
        opts.files = opts.files || opts.file;

        var args,
            conf,
            hasFiles = _.isString(opts.files) || (_.isArray(opts.files) && opts.files.length > 0),
            hasSource = _.isString(opts.source);

        if (!hasFiles && !hasSource) throw new Error(helper.ERR.SOURCE);

        // var cleanupTemp;
        return Promise.resolve()
            .then(function () {
                if (hasFiles) {
                    // expand glob patterns in opts.files array, if any
                    return promiseGlobFiles(opts.files)
                        .then(function (files) {
                            opts.files = files;
                            return opts;
                        });
                }
                if (hasSource) {
                    return helper.createTempFile(opts.source)
                        .then(function (file) {
                            opts.files = [file.path];
                            // cleanupTemp = file.cleanup;
                            return opts;
                        });
                }
            })
            .then(function (opts) {
                args = buildArgs(opts);
                conf = buildConf(opts);
                // return helper.exec(jsdocx.path, args);
                return helper.execJSDoc(jsdocx.path, args, conf);
            })
            .then(function (json) {
                var docs = helper.safeJsonParse(json);
                if (!docs) {
                    throw new Error(helper.ERR.INVALID_OUTPUT);
                }
                docs = jsdocx.filter(docs, opts, opts.predicate || opts.filter);
                if (options.output) {
                    return helper.writeJSON(options.output, docs);
                }
                // cleanup and delete the temp file if created.
                // if (cleanupTemp) cleanupTemp();
                return docs;
            })
            .catch(function (err) {
                // jsdoc err might not be very useful when some arguments are
                // invalid. so, we'll prepend the full command, in case of an
                // error and re-throw.
                var cmd = 'jsdoc ' + args.join(' ');
                err.message = err.message + ' \nExecuted JSDoc Command: ' + cmd + '\n'
                    + 'with JSON configuration: ' + JSON.stringify(conf);
                throw err;
            })
            .nodeify(callback);
    };

    jsdocx.utils = utils;

    // ---------------------------

    return jsdocx;

})();
<commit_msg>moved sort logic to utils<commit_after>// core modules
var path = require('path'),
    fs = require('fs');
// dep modules
var _ = require('lodash'),
    Promise = require('bluebird'),
    glob = require('glob');
// own modules
var helper = require('./lib/helper'),
    utils = require('./lib/utils');

module.exports = (function () {

    var jsdocx = {};
    glob = Promise.promisify(glob);

    // if the dependent project has jsdoc dependency, ours will not be
    // installed. and since we don't use the jsdoc module via require but a
    // specific file (jsdoc.js), we cannot be sure of its location. this method
    // will try to find it if exists.
    var jsdocjs = 'jsdoc/jsdoc.js';
    try {
        var local = path.join('..', 'node_modules', jsdocjs);
        if (fs.existsSync(local)) {
            jsdocx.path = local;
        } else {
            // Use the internal require() machinery to look up the location
            // of a module, but rather than loading the module, just return
            // the resolved filename.
            jsdocx.path = require.resolve(jsdocjs);
            // jsdoc module does not expose a main file. so instead of
            // require.resolve('jsdoc') - which will fail; we'll look for
            // 'jsdoc/jsdoc.js'.

            // for example, if the parent project has it, we'll get:
            // /path/to/parent-project/node_modules/jsdoc/jsdoc.js
        }
    } catch (e) {
        throw new Error('Could not find jsdoc module.');
    }

    // ---------------------------
    // HELPERS
    // ---------------------------

    function identity(o) {
        return o;
    }

    // http://usejsdoc.org/about-commandline.html
    // http://usejsdoc.org/about-configuring-jsdoc.html
    function buildArgs(options) {
        // access, private, readme, template, etc.. These CLI options do not
        // have affect when run with --explain (-X) flag. They are for
        // jsdoc-genrated docs. access is handled within the filter method.
        var opts = _.defaults(options, {
            // files: ... // non-jsdoc option
            encoding: 'utf8',
            package: null, // path
            recurse: false,
            pedantic: false,
            query: null
            // debug: false
            // verbose: false
        });

        var args = ['-X'];
        args = args.concat(helper.ensureArray(opts.files));
        args.push('-e', opts.encoding);
        if (_.isString(opts.package)) {
            args.push('-P', opts.package);
        }
        if (opts.recurse) args.push('-r');
        if (opts.pedantic) args.push('--pedantic');
        if (opts.query) args.push('-q', opts.query);
        // if (opts.debug) args.push('--debug');
        // if (opts.verbose) args.push('--verbose');
        return args;
    }

    // Builds the configuration object for JSDoc. JSDoc takes a filepath for
    // configuration (-c command). So we need to create a temp JSON file. This
    // function creates the conf object to be written to that temp file before
    // passing to jsdoc as a command line argument.
    function buildConf(options) {
        var opts = options || {};

        // updating default JSDoc configuration.
        // see http://usejsdoc.org/about-configuring-jsdoc.html
        return {
            tags: {
                allowUnknownTags: typeof opts.allowUnknownTags === 'boolean'
                    ? opts.allowUnknownTags
                    : true,
                dictionaries: !Array.isArray(opts.dictionaries)
                    ? ['jsdoc', 'closure']
                    : opts.dictionaries
            },
            source: {
                includePattern: opts.includePattern || '.+\\.js(doc|x)?$',
                excludePattern: opts.excludePattern || '(^|\\/|\\\\)_'
            },
            plugins: !Array.isArray(opts.plugins) ? [] : opts.plugins,
            templates: {
                cleverLinks: false,
                monospaceLinks: false
            }
        };
    }

    function relativePath(symbol, rPath) {
        if (!symbol || !rPath) return;
        var p = symbol.meta && helper.getStr(symbol.meta.path);
        if (p) {
            symbol.meta.path = helper.normalizePath(path.relative(p, rPath));
        }
    }

    function normalizeAccess(access) {
        // ['public', 'protected', 'private'];
        if (access === 'all') return access; // all
        if (!_.isString(access) && !_.isArray(access)) {
            return ['public', 'protected'];
        }
        return helper.ensureArray(access);
    }

    // sorts documentation symbols and properties of each symbol, if any.
    function sortDocs(docs, sortType) {
        if (!sortType) return;
        var sorter = utils._getSorter(sortType, '$longname'),
            propSorter = utils._getSorter(sortType, 'name');
        docs.sort(sorter);
        docs.forEach(function (symbol) {
            if (symbol && Array.isArray(symbol.properties)) {
                symbol.properties.sort(propSorter);
            }
        });
    }

    function hierarchy(docs, sortType) {
        var parent,
            sorter = utils._getSorter(sortType, '$longname'),
            propSorter = utils._getSorter(sortType, 'name');
        _.eachRight(docs, function (symbol, index) {
            // Move constructor (method definition) to class declaration symbol
            if (utils.isConstructor(symbol)) {
                parent = _.find(docs, function (o) {
                    return o.longname === symbol.longname && utils.isClass(o);
                });
                if (parent) {
                    parent.$constructor = symbol;
                    docs.splice(index, 1);
                }
            // otherwise, move symbols with memberof property to corresponding parent member.
            } else if (symbol.memberof) {
                // first check and sort if it has properties
                if (propSorter && Array.isArray(symbol.properties)) {
                    symbol.properties.sort(propSorter);
                }

                parent = _.find(docs, { longname: symbol.memberof });
                if (parent) {
                    parent.$members = parent.$members || [];
                    parent.$members.push(symbol);
                    if (sorter) {
                        parent.$members.sort(sorter);
                    } else {
                        // reverse bec. we used eachRight
                        parent.$members.reverse();
                    }
                    docs.splice(index, 1);
                }
            }
        });
        if (sorter) docs.sort(sorter);
        return docs;
    }

    function promiseGlobFiles(globs) {
        globs = helper.ensureArray(globs);
        return Promise.reduce(globs, function (memo, pattern) {
            return glob(pattern).then(function (paths) {
                return memo.concat(paths);
            });
        }, []);
    }

    // ---------------------------
    // PUBLIC METHODS
    // ---------------------------

    /**
     *  Filters the parsed documentation output array.
     *
     *  @param {Array} docs - Documentation output array.
     *  @param {Object} [options] - Filter options.
     *  @param {Function} [predicate] - The function invoked per iteration.
     *  Returning a falsy value will remove the symbol from the output.
     *  Returning true will keep the original symbol. To keep the symbol and
     *  alter its contents, simply return an altered symbol object.
     *
     *  @returns {Array} - Filtered documentation array.
     */
    jsdocx.filter = function (docs, options, predicate) {
        if (!options && !predicate) return docs;
        if (_.isFunction(options)) {
            predicate = options;
            options = {};
        }
        if (!_.isFunction(predicate)) predicate = identity;
        docs = helper.ensureArray(docs);

        options = _.defaults(options, {
            access: undefined,
            package: true,
            module: true,
            undocumented: true,
            undescribed: true,
            hierarchy: false,
            sort: false, // (true|"alphabetic")|"grouped"|false
            relativePath: null
        });

        var access = normalizeAccess(options.access);
        var isCon, undoc, undesc, pkg, mdl, acc, o;
        docs = _.reduce(docs, function (memo, symbol) {
            // console.log(symbol.longname, symbol.kind, symbol.access, symbol.meta ? symbol.meta.code.type : '');

            // JSDoc overwrites the `longname` and `name` of the symbol, if it
            // has an alias. See https://github.com/jsdoc3/jsdoc/issues/1217 and
            // documentation of jsdocx.utils.getFullName()
            symbol.$longname = utils.getLongName(symbol);

            undoc = options.undocumented || symbol.undocumented !== true;
            undesc = options.undescribed || utils.hasDescription(symbol);
            pkg = options.package || symbol.kind !== 'package';
            mdl = options.module || symbol.longname !== 'module.exports';
            // access might not be explicitly set for the symbol.
            // in this case, we'll include the symbol.
            acc = access === 'all' || !symbol.access || access.indexOf(symbol.access) >= 0;
            // constructor symbol is undocumented=true even if it's documented
            isCon = acc && utils.isConstructor(symbol);
            if (isCon || (undoc && undesc && pkg && mdl && acc)) {
                relativePath(symbol, options.relativePath);
                o = predicate(symbol);
                if (_.isPlainObject(o)) {
                    memo.push(o); // filtered symbol pushed
                } else if (o) { // boolean check
                    memo.push(symbol); // original symbol pushed
                }
            }
            return memo;
        }, []);

        if (options.hierarchy) {
            docs = hierarchy(docs, options.sort);
        } else if (options.sort) {
            sortDocs(docs, options.sort);
        }
        return docs;
    };

    /**
     * Executes the `jsdoc` command and parses the output into a Javascript
     * object/array; with the specified options.
     *
     * @param {Object|String|Array} options - Either an options object or one
     * or more source files to be processed.
     * @param {Function} [callback] - Callback function to be executed
     * in the following signature: function (err, array) { ... }`
     * Omit this callback to return a `Promise`.
     *
     * @returns {void|Promise} - Returns a `Promise` if `callback` is omitted.
     */
    jsdocx.parse = function (options, callback) {
        if (!options) throw new Error(helper.ERR.SOURCE);
        var opts = !_.isPlainObject(options)
            ? { files: options }
            : options;
        opts.files = opts.files || opts.file;

        var args,
            conf,
            hasFiles = _.isString(opts.files) || (_.isArray(opts.files) && opts.files.length > 0),
            hasSource = _.isString(opts.source);

        if (!hasFiles && !hasSource) throw new Error(helper.ERR.SOURCE);

        // var cleanupTemp;
        return Promise.resolve()
            .then(function () {
                if (hasFiles) {
                    // expand glob patterns in opts.files array, if any
                    return promiseGlobFiles(opts.files)
                        .then(function (files) {
                            opts.files = files;
                            return opts;
                        });
                }
                if (hasSource) {
                    return helper.createTempFile(opts.source)
                        .then(function (file) {
                            opts.files = [file.path];
                            // cleanupTemp = file.cleanup;
                            return opts;
                        });
                }
            })
            .then(function (opts) {
                args = buildArgs(opts);
                conf = buildConf(opts);
                // return helper.exec(jsdocx.path, args);
                return helper.execJSDoc(jsdocx.path, args, conf);
            })
            .then(function (json) {
                var docs = helper.safeJsonParse(json);
                if (!docs) {
                    throw new Error(helper.ERR.INVALID_OUTPUT);
                }
                docs = jsdocx.filter(docs, opts, opts.predicate || opts.filter);
                if (options.output) {
                    return helper.writeJSON(options.output, docs);
                }
                // cleanup and delete the temp file if created.
                // if (cleanupTemp) cleanupTemp();
                return docs;
            })
            .catch(function (err) {
                // jsdoc err might not be very useful when some arguments are
                // invalid. so, we'll prepend the full command, in case of an
                // error and re-throw.
                var cmd = 'jsdoc ' + args.join(' ');
                err.message = err.message + ' \nExecuted JSDoc Command: ' + cmd + '\n'
                    + 'with JSON configuration: ' + JSON.stringify(conf);
                throw err;
            })
            .nodeify(callback);
    };

    jsdocx.utils = utils;

    // ---------------------------

    return jsdocx;

})();
<|endoftext|>


<commit_before>export default function createMeta(type) {
  let sameActionType = false;
  let actionTypes = { request: 'request', success: 'success', failure: 'failure' };

  if (typeof type === 'string') {
    if (!type.length) {
      throw new Error('Missing action type given to createMeta.');
    }
    sameActionType = true;
  } else {
    const { request, success, failure } = type;
    if (!request || !success || !failure) {
      throw new Error('Missing or invalid action type(s) given to createMeta.');
    }
    actionTypes = { request, success, failure };
  }

  const initialState = { isFetching: false, lastUpdated: undefined, error: false };

  return (state = initialState, action = {}) => {
    const { error = true } = action;

    if (sameActionType && action.type !== type) {
      return state;
    }

    switch (sameActionType ? action.status : action.type) {
      case actionTypes.request:
        return Object.assign({}, state, { isFetching: true });
      case actionTypes.success:
        return { isFetching: false, lastUpdated: action.now, error: false };
      case actionTypes.failure:
        return { isFetching: false, lastUpdated: action.now, error };
      default:
        return state;
    }
  };
}
<commit_msg>small refactor to createMeta<commit_after>export default function createMeta(type) {
  let sameActionType = true;
  let actionTypes = { request: 'request', success: 'success', failure: 'failure' };

  if (typeof type === 'string') {
    if (!type.length) {
      throw new Error('Missing action type given to createMeta.');
    }
  } else {
    const { request, success, failure } = type;
    if (!request || !success || !failure) {
      throw new Error('Missing or invalid action type(s) given to createMeta.');
    }
    sameActionType = false;
    actionTypes = { request, success, failure };
  }

  const initialState = { isFetching: false, lastUpdated: undefined, error: false };

  return (state = initialState, action = {}) => {
    const { error = true } = action;

    if (sameActionType && action.type !== type) {
      return state;
    }

    switch (sameActionType ? action.status : action.type) {
      case actionTypes.request:
        return Object.assign({}, state, { isFetching: true });
      case actionTypes.success:
        return { isFetching: false, lastUpdated: action.now, error: false };
      case actionTypes.failure:
        return { isFetching: false, lastUpdated: action.now, error };
      default:
        return state;
    }
  };
}
<|endoftext|>


<commit_before>/* global require, module, Buffer */

var through = require('through2');
var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var md = require('markdown-it')();

var parseMarkdown = function (text) {
    'use strict';
    return md.parse(text);
};

var tailorElement = null;
var tailorElementSequence = function (s) {
    if (s) {
        return _.map(s, tailorElement);
    } else {
        return undefined;
    }
};
tailorElement = function (e) {
    if (e) {
        var e2 = { type: e.type };
        if (e.tag) e2.tag = e.tag;
        if (e.markup) e2.markup = e.markup;
        if (e.content) e2.content = e.content;
        if (e.children) e2.children = tailorElementSequence(e.children);
        return e2;
    } else {
        return e;
    }
};

var buildTree = function (s) {
    var tree = { typ: 'r', text: null, level: 0, children: [] };
    var pivot = tree;
    var stack = [tree];
    var inHeading = false;

    var push = function (typ, text, level) {
        var p = {
            typ: typ,
            text: text,
            level: level,
            children: []
        };
        pivot.children.push(p);
        pivot = p;
        stack.push(p);
    };
    var pop = function () {
        stack.pop();
        pivot = _.last(stack);
    };
    var extractId = function (n) {
        var m = n.text.match(/\s+\{[ \t]*#(\S+)[ \t]*\}$/);
        if (m) {
            n.text = n.text.slice(0, n.text.length - m[0].length);
            n.id = m[1];
        }
    };

    _.forEach(s, function (e) {
        if (!inHeading) {
            if (e.type == 'heading_open') {
                inHeading = true;
                var level = Number.parseInt(e.tag.slice(1));
                for (var i = _.size(stack); i > level; i--) {
                    pop();
                }
                for (var i = _.size(stack); i < level; i++) {
                    push('h', null, i);
                }
                push('h', '', level);
            }
            else if (e.type == 'list_item_open') {
                push('l', '', _.size(stack));
            }
            else if (e.type == 'list_item_close') {
                pop();
            }
            else if (e.type == 'inline') {
                if (pivot.typ == 'l') {
                    pivot.text += e.content;
                }
            }
        }
        else if (inHeading) {
            if (e.type == 'inline') {
                pivot.text += e.content;
            }
            else if (e.type == 'heading_close') {
                extractId(pivot);
                inHeading = false;
            }
        }
    });
    return tree;
};

var nodeFromText = function (text) {
    if (text == null || text.trim().length == 0) {
        return { };
    }
    var p = text.indexOf(':');
    if (p >= 0) {
        return {
            name: text.slice(0, p).trim(),
            value: text.slice(p + 1).trim()
        };
    } else {
        return { name: text.trim() };
    }
};

var transformTree = function transformTree (n) {
    var n2 = nodeFromText(n.text);
    if (n.id) {
        n2.id = n.id;
    }
    if (_.size(n.children) == 0) {
        if (!n2.value) {
            return n2.name;
        }
    } else {
        n2.children = _.map(n.children, transformTree);
    }
    return n2;
};

var transformDocumentToData = function (doc) {
    'use strict';
    var elements = tailorElementSequence(doc);
    var tree = buildTree(elements);
    return transformTree(tree).children;
};

var extractDataFromMarkdown = function (text) {
    'use strict';
    return transformDocumentToData(parseMarkdown(text));
};

var transformText = function (text) {
    'use strict';
    var data = extractDataFromMarkdown(text);
    // return JSON.stringify(data, null, '  ');
    return data;
};

var transformBuffer = function (buffer) {
    'use strict';
    return new Buffer(transformText(buffer.toString('utf8')), 'utf8');
};

var transformFile = function (filePath) {
    'use strict';
    if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) {
        throw 'File not found.';
    }
    var referencePath = path.dirname(filePath);
    var text = fs.readFileSync(filePath, 'utf8');
    return transformText(text, referencePath);
};

var extractor = function (fileOrText) {
    'use strict';

    if (fileOrText) {
        if (typeof(fileOrText) === 'string') {
            try {
                fs.accessSync(fileOrText, fs.R_OK);
                // extractor(filePath) -> returns the processed content of the file
                return transformFile(fileOrText);
            } catch (e) {
                console.log(e);
                // extractor(text) -> returns the processed text
                return transformText(fileOrText);
            }
        } else {
            throw 'Invalid first argument.';
        }
    }

    // extractor() -> gulp transformation step
    return through.obj(function (file, enc, cb) {
        if (file.isNull()) {
            this.push(file);
            cb();
            return;
        }
        if (file.isBuffer()) {
            file.contents = transformBuffer(file.contents, path.dirname(file.path));
            this.push(file);
            cb();
            return;
        }
        if (file.isStream()) {
            throw 'Streams are not supported.';
        }
    });
};

module.exports = extractor;
<commit_msg>improved file access check, fixed markdown-it bug due to calling without options<commit_after>/* global require, module, Buffer */

var through = require('through2');
var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var md = require('markdown-it')();

var parseMarkdown = function (text) {
    'use strict';
    return md.parse(text, {});
};

var tailorElement = null;
var tailorElementSequence = function (s) {
    if (s) {
        return _.map(s, tailorElement);
    } else {
        return undefined;
    }
};
tailorElement = function (e) {
    if (e) {
        var e2 = { type: e.type };
        if (e.tag) e2.tag = e.tag;
        if (e.markup) e2.markup = e.markup;
        if (e.content) e2.content = e.content;
        if (e.children) e2.children = tailorElementSequence(e.children);
        return e2;
    } else {
        return e;
    }
};

var buildTree = function (s) {
    var tree = { typ: 'r', text: null, level: 0, children: [] };
    var pivot = tree;
    var stack = [tree];
    var inHeading = false;

    var push = function (typ, text, level) {
        var p = {
            typ: typ,
            text: text,
            level: level,
            children: []
        };
        pivot.children.push(p);
        pivot = p;
        stack.push(p);
    };
    var pop = function () {
        stack.pop();
        pivot = _.last(stack);
    };
    var extractId = function (n) {
        var m = n.text.match(/\s+\{[ \t]*#(\S+)[ \t]*\}$/);
        if (m) {
            n.text = n.text.slice(0, n.text.length - m[0].length);
            n.id = m[1];
        }
    };

    _.forEach(s, function (e) {
        if (!inHeading) {
            if (e.type == 'heading_open') {
                inHeading = true;
                var level = Number.parseInt(e.tag.slice(1));
                for (var i = _.size(stack); i > level; i--) {
                    pop();
                }
                for (var i = _.size(stack); i < level; i++) {
                    push('h', null, i);
                }
                push('h', '', level);
            }
            else if (e.type == 'list_item_open') {
                push('l', '', _.size(stack));
            }
            else if (e.type == 'list_item_close') {
                pop();
            }
            else if (e.type == 'inline') {
                if (pivot.typ == 'l') {
                    pivot.text += e.content;
                }
            }
        }
        else if (inHeading) {
            if (e.type == 'inline') {
                pivot.text += e.content;
            }
            else if (e.type == 'heading_close') {
                extractId(pivot);
                inHeading = false;
            }
        }
    });
    return tree;
};

var nodeFromText = function (text) {
    if (text == null || text.trim().length == 0) {
        return { };
    }
    var p = text.indexOf(':');
    if (p >= 0) {
        return {
            name: text.slice(0, p).trim(),
            value: text.slice(p + 1).trim()
        };
    } else {
        return { name: text.trim() };
    }
};

var transformTree = function transformTree (n) {
    var n2 = nodeFromText(n.text);
    if (n.id) {
        n2.id = n.id;
    }
    if (_.size(n.children) == 0) {
        if (!n2.value) {
            return n2.name;
        }
    } else {
        n2.children = _.map(n.children, transformTree);
    }
    return n2;
};

var transformDocumentToData = function (doc) {
    'use strict';
    var elements = tailorElementSequence(doc);
    var tree = buildTree(elements);
    return transformTree(tree).children;
};

var extractDataFromMarkdown = function (text) {
    'use strict';
    return transformDocumentToData(parseMarkdown(text));
};

var transformText = function (text) {
    'use strict';
    var data = extractDataFromMarkdown(text);
    return data;
};

var transformBuffer = function (buffer) {
    'use strict';
    return new Buffer(transformText(buffer.toString('utf8')), 'utf8');
};

var transformFile = function (filePath) {
    'use strict';
    var referencePath = path.dirname(filePath);
    var text = fs.readFileSync(filePath, 'utf8');
    return transformText(text, referencePath);
};

var canReadFile = function (path) {
    try {
        fs.accessSync(path, fs.R_OK);
        return true;
    } catch (e) {
        return false;
    }
};

var extractor = function (fileOrText) {
    'use strict';

    if (fileOrText) {
        if (typeof(fileOrText) === 'string') {
            if (canReadFile(fileOrText)) {
                // extractor(filePath) -> returns the extracted data of the file
                return transformFile(fileOrText);
            } else {
                // extractor(text) -> returns the extracted data of the text
                return transformText(fileOrText);
            }
        } else {
            throw 'Invalid first argument.';
        }
    }

    // extractor() -> gulp transformation step
    return through.obj(function (file, enc, cb) {
        if (file.isNull()) {
            this.push(file);
            cb();
            return;
        }
        if (file.isBuffer()) {
            file.contents = transformBuffer(file.contents, path.dirname(file.path));
            this.push(file);
            cb();
            return;
        }
        if (file.isStream()) {
            throw 'Streams are not supported.';
        }
    });
};

module.exports = extractor;
<|endoftext|>


<commit_before>'use strict';
let {makeHTTPDriver} = require('./http-driver');

module.exports = {
  /**
   * HTTP Driver factory. This is a function which, when called, returns a HTTP
   * Driver for Cycle.js apps. The driver is also a function, and it takes an
   * Observable of requests as input, and generates a metastream of responses. A
   * metastream is an Observable of Observables. The response metastream emits
   * Observables of responses. These Observables of responses have a `request`
   * field attached to them (to the Observable object itself) indicating which
   * request (from the driver input) generated this response Observable. The
   * response Observables themselves emit the response object received through
   * superagent.
   *
   * @return {Function} the HTTP Driver function
   * @function makeHTTPDriver
   */
  makeHTTPDriver
};
<commit_msg>Fix code style issues in src/index.js<commit_after>'use strict';
let {makeHTTPDriver} = require('./http-driver');

module.exports = {
  /**
   * HTTP Driver factory. This is a function which, when called, returns a HTTP
   * Driver for Cycle.js apps. The driver is also a function, and it takes an
   * Observable of requests as input, and generates a metastream of responses. A
   * metastream is an Observable of Observables. The response metastream emits
   * Observables of responses. These Observables of responses have a `request`
   * field attached to them (to the Observable object itself) indicating which
   * request (from the driver input) generated this response Observable. The
   * response Observables themselves emit the response object received through
   * superagent.
   *
   * @return {Function} the HTTP Driver function
   * @function makeHTTPDriver
   */
  makeHTTPDriver
};
<|endoftext|>


<commit_before>/**
  * BEM helper for generating CSS class names in JS
  * Returns a chainable API
  *
  * @author David Lindkvist
  */

class BEM {
	constructor(block) {
		this.block = block;
		this.element = undefined;
		this.modifiers = [];
		this.nonBemClasses = [];
	}

	// Set element scope
	el(elementIdentifier) {
		if (typeof elementIdentifier !== 'undefined'
			&& elementIdentifier.toString().length) {
			this.element = elementIdentifier;
		}
		return this;
	}

	// Add BEM modifier
	is(modifier, isOn = true) {
		isOn && typeof modifier !== 'undefined'
		     && modifier.toString().length
		     && this.modifiers.push(modifier);
		return this;
	}

	// Add other non-BEM classname to the mix
	add(className) {
		if (typeof className !== 'undefined'
			&& className.toString().length) {
			this.nonBemClasses.push(className);
		}
		return this;
	}

	// Render BEM chain as full class name string
	toString() {
		let prefix = typeof this.element !== 'undefined' ? this.block + '__' + this.element : this.block;
		const classes = [prefix];
		for (let modifier of this.modifiers) {
			classes.push(prefix + '--' + modifier);
		}
		for (let extraClass of this.nonBemClasses) {
			classes.push(extraClass);
		}
		return classes.join(' ');
	}
}

// Creates BEM chain based on context type
export default function(ctx) {
	if (typeof ctx === 'object') {
		if (ctx instanceof BEM) {
			return ctx;
		}
		return new BEM(ctx.constructor.name);
	}
	else if (typeof ctx === 'string') {
		return new BEM(ctx);
	}
	throw "BEM block not of valid type";
}<commit_msg>Added support for "building blocks"<commit_after>/**
  * BEM helper for generating CSS class names in JS
  * Returns a chainable API
  *
  * @author David Lindkvist
  */

class BEM {
	constructor(block, element, modifiers = [], nonBemClasses = []) {
		this.block = block;
		this.element = element;
		this.modifiers = modifiers;
		this.nonBemClasses = nonBemClasses;
	}

	// Set element scope
	el(elementIdentifier) {
		let newBlock = this.clone()
		if (typeof elementIdentifier !== 'undefined'
			&& elementIdentifier.toString().length) {
			newBlock.element = elementIdentifier;
		}
		return newBlock;
	}

	// Add BEM modifier
	is(modifier, isOn = true) {
		let modifiers = this.modifiers.slice();
		isOn && typeof modifier !== 'undefined'
		     && modifier.toString().length
		     && modifiers.push(modifier);
		let newBlock = this.clone({
			modifiers: modifiers,
			nonBemClasses: this.nonBemClasses
		})
		return newBlock
	}

	// Add other non-BEM classname to the mix
	add(className) {
		let nonBemClasses = this.nonBemClasses.slice();
		if (typeof className !== 'undefined'
			&& className.toString().length) {
			nonBemClasses.push(className);
		}
		let newBlock = this.clone({
			nonBemClasses: nonBemClasses,
			modifiers: this.modifiers
		})
		return newBlock
	}

	// Render BEM chain as full class name string
	toString() {
		let prefix = typeof this.element !== 'undefined' ? this.block + '__' + this.element : this.block;
		const classes = [prefix];
		for (let modifier of this.modifiers) {
			classes.push(prefix + '--' + modifier);
		}
		for (let extraClass of this.nonBemClasses) {
			classes.push(extraClass);
		}
		return classes.join(' ');
	}

	clone(newBlock = {}) {
		return new BEM(this.block, this.element, newBlock.modifiers, newBlock.nonBemClasses)
	}
}

// Creates BEM chain based on context type
export default function(ctx) {
	if (typeof ctx === 'object') {
		if (ctx instanceof BEM) {
			return ctx;
		}
		return new BEM(ctx.constructor.name);
	}
	else if (typeof ctx === 'string') {
		return new BEM(ctx);
	}
	throw "BEM block not of valid type";
}
<|endoftext|>