<commit_before>/** @babel */
/** @jsx etch.dom */

import etch from 'etch'
import PkgListComponent from './pkg-list-component'

/**
 * This is the "big" view -- a pane to set up package groups. A different
 * view will be used to just enable/disable groups.
 */
export default class PkgGroupsView {
  constructor (props, children) {
    this.props = props || {}
    this.children = children || []
    this.onAddGroup = this.onAddGroup.bind(this)
    this.getPackageList()
    etch.initialize(this)
  }

  onAddGroup (evt) {
    /* eslint no-console: "off" */
    console.log('button add group pushed')
  }

  render () {
    let listitems = []
    let groups = this.props['groups'] || []
    groups.forEach((name) => {
      listitems.push(
{name}
)
    })

    let packages = this.props['packages'] || []

    let pkgcomp
    if (packages.length === 0) {
      pkgcomp =
Loading packages…

    } else {
      /* pkgcomp = <PkgListComponent packages={packages} /> */
      pkgcomp = new PkgListComponent({'packages': packages})
      if (pkgcomp === undefined) {
        throw new Error('Failed to create pkg list component!')
      }
    }

    // Create root element
    this.element =

      <atom-panel className='modal' id='group-select-panel'>

Package Groups Setup

Defined Groups

                {listitems}

Everything

                <button className='btn btn-primary icon icon-plus' type='button'
                  onClick={this.onAddGroup}>
                  New Group
                </button>

Modify Group

              {pkgcomp}

There are {packages.length} avallable packages.

      </atom-panel>

    return this.element
  }

  update (props, children) {
    this.props = props
    this.children = children
    return etch.update(this)
  }

  async getPackageList () {
    let pkgList = []
    const pkgs = await atom.packages.getAvailablePackageNames()
    pkgs.then(() => {
      this.props['packages'] = pkgs
      this.update(this.props, this.children)
    })
  }

  getTitle () {
    // for Atom tab
    return 'Package Groups'
  }

  getURI () {
    return 'atom://pkg-groups'
  }

  // Returns an object that can be retrieved when package is activated
  serialize () {
    return {
      deserializer: 'pkg-groups/PkgGroupsView',
      props: this.props,
      children: this.children
    }
  }

  // Tear down any state and detach
  async destroy () {
    await etch.destroy(this)
  }

  getElement () {
    return this.element
  }
}
<commit_msg>some fixes, complete serialize()<commit_after>/** @babel */
/** @jsx etch.dom */

import etch from 'etch'
import PkgListComponent from './pkg-list-component'

/**
 * This is the "big" view -- a pane to set up package groups. A different
 * view will be used to just enable/disable groups.
 */
export default class PkgGroupsView {
  constructor (props, children) {
    this.props = props || {}
    this.children = children || []
    this.onAddGroup = this.onAddGroup.bind(this)
    this.getPackageList()
    etch.initialize(this)
  }

  onAddGroup (evt) {
    /* eslint no-console: "off" */
    console.log('button add group pushed')
  }

  render () {
    let listitems = []
    let groups = this.props['groups'] || []
    groups.forEach((name) => {
      listitems.push(
{name}
)
    })

    let packages = this.props['packages'] || []

    let pkgcomp
    if (packages.length === 0) {
      pkgcomp =
Loading packages…

    } else {
      /* pkgcomp = <PkgListComponent packages={packages} /> */
      pkgcomp = new PkgListComponent({'packages': packages})
      if (pkgcomp === undefined) {
        throw new Error('Failed to create pkg list component!')
      }
    }

    // Create root element
    this.element =

      <atom-panel className='modal' id='group-select-panel'>

Package Groups Setup

Defined Groups

                {listitems}

Everything

                <button className='btn btn-primary icon icon-plus' type='button'
                  onClick={this.onAddGroup}>
                  New Group
                </button>

Modify Group

              {pkgcomp}

There are {packages.length} avallable packages.

      </atom-panel>

    return this.element
  }

  update (props, children) {
    this.props = props
    this.children = children
    return etch.update(this)
  }

  async getPackageList () {
    const pkgs = await atom.packages.getAvailablePackageNames()
    this.props['packages'] = pkgs
    this.update(this.props, this.children)
  }

  getTitle () {
    // for Atom tab
    return 'Package Groups'
  }

  getURI () {
    return 'atom://pkg-groups'
  }

  // Returns an object that can be retrieved when package is activated
  serialize () {
    return {
      deserializer: 'pkg-groups/PkgGroupsView',
      props: this.props,
      children: this.children
    }
  }

  // Tear down any state and detach
  async destroy () {
    await etch.destroy(this)
  }

  getElement () {
    return this.element
  }
}
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var moment = require('moment');
var times = require('../times');
var levels = require('../levels');
var timeago = require('./timeago')();

function init() {

  var openaps = {
    name: 'openaps'
    , label: 'OpenAPS'
    , pluginType: 'pill-status'
  };

  openaps.getPrefs = function getPrefs(sbx) {
    return {
      warn: sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 30,
      urgent: sbx.extendedSettings.urgent ? sbx.extendedSettings.urgent : 60,
      enableAlerts: sbx.extendedSettings.enableAlerts
    };
  };

  openaps.setProperties = function setProperties (sbx) {
    sbx.offerProperty('openaps', function setopenaps ( ) {
      var openapsStatus = _.findLast(sbx.data.devicestatus, function (status) {
        return sbx.entryMills(status) <= sbx.time && ('openaps' in status);
      });

      var loopStatus = checkLoopStatus(openapsStatus, sbx);
      openapsStatus = openapsStatus || {};
      openapsStatus.status = loopStatus;

      return openapsStatus;
    });
  };

  openaps.getEventTypes = function getEventTypes ( ) {
    return [
      {
        val: 'OpenAPS Offline'
        , name: 'OpenAPS Offline'
        , bg: false, insulin: false, carbs: false, prebolus: false, duration: true, percent: false, absolute: false, profile: false, split: false
      }
    ];
  };

  openaps.checkNotifications = function checkNotifications(sbx) {
    var prefs = openaps.getPrefs(sbx);

    if (!prefs.enableAlerts) { return; }

    var prop = sbx.properties.openaps;
    var ops = prepOps(prop, sbx);

    if (!ops.lastLoopTime) {
      console.info('OpenAPS hasn\'t reported a loop yet');
      return;
    }

    var now = moment();
    var level = statusLevel(ops, prefs, sbx);
    if (level >= levels.WARN) {
      sbx.notifications.requestNotify({
        level: level
        , title: 'OpenAPS isn\'t looping'
        , message: 'Last Loop: ' + formatAgo(ops.lastLoopTime, now.valueOf())
        , pushoverSound: 'echo'
        , plugin: openaps
        , debug: ops
      });
    }
  };

  openaps.updateVisualisation = function updateVisualisation (sbx) {
    var prop = sbx.properties.openaps;

    var info = [];

    info.push({label: timeFormat(prop.status.when, sbx), value: prop.status.label});

    var ops = prepOps(prop, sbx);
    var prefs = openaps.getPrefs(sbx);

    function valueString (prefix, value) {
      return value ? prefix + value : '';
    }

    function addSuggestion() {
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.suggestedTime, sbx)
        , value: [
          valueString('BG: ', ops.suggested.bg)
          , valueString(', ', ops.suggested.reason)
          , ops.suggested.mealAssist ? ' Meal Assist: ' + ops.suggested.mealAssist : ''
        ].join('')
      });
    }

    if ('enacted' === prop.status.code) {
      if (ops.suggestedTime.isAfter(ops.enactedTime)) {
        addSuggestion();
      }
      var canceled = ops.enacted.rate === 0 && ops.enacted.duration === 0;
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.enactedTime, sbx)
        , value: [
          valueString('BG: ', ops.enacted.bg)
          , ', Temp Basal' + (canceled ? ' Canceled' : ' Started') + ''
          , canceled ? '' : ' ' + ops.enacted.rate.toFixed(2) + ' for ' + ops.enacted.duration + 'm'
          , valueString(', ', ops.enacted.reason)
          , ops.enacted.mealAssist ? ' Meal Assist: ' + ops.enacted.mealAssist : ''
        ].join('')
      });
    } else if ('notenacted' === prop.status.code) {
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.notEnactedTime, sbx)
        , value: 'Not Enacted'
      });
    } else if ('looping' === prop.status.code) {
      addSuggestion();
    } else if (ops.lastLoopTime) {
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.lastLoopTime, sbx)
        , value: 'Last Loop'
      });
    }

    if (ops.iob && ops.iobTime.isAfter(ops.recent)) {
      var bolussnooze = ops.iob.bolussnooze || ops.iob.bolusiob;
      info.push({
        label: 'IOB'
        , value: [
          sbx.roundInsulinForDisplayFormat(ops.iob.iob) + 'U'
          , ops.iob.basaliob ? ', Basal IOB ' + sbx.roundInsulinForDisplayFormat(ops.iob.basaliob) + 'U' : ''
          , bolussnooze ? ', Bolus Snooze ' + sbx.roundInsulinForDisplayFormat(bolussnooze) + 'U' : ''
          , timeAt(true, sbx) + timeFormat(ops.iobTime, sbx)
        ].join('')
      });
    }

    if (ops.pumpTime && ops.pumpTime.isAfter(ops.recent)) {
      info.push({label: 'Last Pump Clock', value: ops.pumpTime.format('LT')});
    }

    sbx.pluginBase.updatePillText(openaps, {
      value: timeFormat(ops.lastLoopTime, sbx)
      , label: 'OpenAPS ' + prop.status.symbol
      , info: info
      , pillClass: statusClass(ops, prefs, sbx)
    });
  };

  return openaps;

}

function statusClass (ops, prefs, sbx) {
  var level = statusLevel(ops, prefs, sbx);
  var cls = 'current';

  if (level === levels.WARN) {
    cls = 'warn';
  } else if (level === levels.URGENT) {
    cls = 'urgent';
  }

  return cls;
}

function statusLevel (ops, prefs, sbx) {
  var level = levels.NONE;
  var now = moment(sbx.time);

  var offlineMarker = _.findLast(sbx.data.treatments, function match (treatment) {
    var eventTime = sbx.entryMills(treatment);
    var eventEnd = treatment.duration ? eventTime + times.mins(treatment.duration).msecs : eventTime;
    return eventTime <= sbx.time && treatment.eventType === 'OpenAPS Offline' && eventEnd >= sbx.time;
  });

  if (offlineMarker) {
    console.info('OpenAPS known offline, not checking for alerts');
  } else if (ops.lastLoopTime) {
    var urgentTime = ops.lastLoopTime.clone().add(prefs.urgent, 'minutes');
    var warningTime = ops.lastLoopTime.clone().add(prefs.warn, 'minutes');

    if (urgentTime.isBefore(now)) {
      level = levels.URGENT;
    } else if (warningTime.isBefore(now)) {
      level = levels.WARN;
    }
  }

  return level;
}

function checkLoopStatus (openapsStatus, sbx)  {

  var status = {
    symbol: '⚠'
    , code: 'warning'
    , label: 'Warning'
  };

  if (openapsStatus) {
    var enactedLast = openapsStatus.openaps.enacted && openapsStatus.openaps.enacted.recieved && moment(openapsStatus.openaps.enacted.timestamp);
    var notEnactedLast = openapsStatus.openaps.enacted && !openapsStatus.openaps.enacted.recieved && moment(openapsStatus.openaps.enacted.timestamp);
    var suggestedLast = openapsStatus.openaps.suggested && moment(openapsStatus.openaps.suggested.timestamp);

    var last =  moment(openapsStatus.mills);
    var recent = moment(sbx.time).subtract(15, 'minutes');

    if (notEnactedLast && notEnactedLast.isAfter(recent)) {
      status.symbol = 'x';
      status.code = 'notenacted';
      status.label = 'Not Enacted';
    } else if (enactedLast && enactedLast.isAfter(recent)) {
      status.symbol = '⌁';
      status.code = 'enacted';
      status.label = 'Enacted';
    } else if (suggestedLast && suggestedLast.isAfter(recent)) {
      status.symbol = '↻';
      status.code = 'looping';
      status.label = 'Looping';
    } else if (last && last.isAfter(recent)) {
      status.symbol = '◉';
      status.code = 'waiting';
      status.label = 'Waiting';
    }

    status.when = last;
  }

  return status;
}

function prepOps (prop, sbx) {

  var recent = moment(sbx.time).subtract(15, 'minutes');
  var iob = prop.openaps && prop.openaps.iob;
  var pump = prop.pump;
  var suggested = prop.openaps && prop.openaps.suggested;
  var suggestedTime = suggested && moment(suggested.timestamp);

  var enacted = null;
  var notEnacted = null;

  if (prop.openaps && prop.openaps.enacted && prop.openaps.enacted.recieved) {
    enacted = prop.openaps.enacted;
  }

  if (prop.openaps && !prop.openaps.enacted && prop.openaps.enacted.recieved) {
    notEnacted = prop.openaps.enacted;
  }

  var enactedTime = enacted && moment(enacted.timestamp);
  var notEnactedTime = notEnacted && moment(notEnacted.timestamp);

  return {
    recent: recent
    , suggested: suggested
    , suggestedTime: suggestedTime
    , enacted: enacted
    , enactedTime: enactedTime
    , notEnacted: enacted
    , notEnactedTime: enactedTime
    , iob: iob
    , iobTime: iob && moment(iob.timestamp)
    , pump: pump
    , pumpTime: pump && pump.clock && moment(pump.clock)
    , lastLoopTime: suggestedTime && enactedTime ? moment.max(suggestedTime, enactedTime) : enactedTime || suggestedTime
  };
}

function timeFormat (m, sbx) {

  var when;
  if (m && sbx.data.inRetroMode) {
    when = m.format('LT');
  } else if (m) {
    when = formatAgo(m, sbx.time);
  } else {
    when = 'unknown';
  }

  return when;
}

function formatAgo (m, nowMills) {
  var ago = timeago.calcDisplay({mills: m.valueOf()}, nowMills);
  return (ago.value ? ago.value : '') + ago.shortLabel + (ago.shortLabel.length === 1 ? ' ago' : '');
}

function timeAt (prefix, sbx) {
  return sbx.data.inRetroMode ? (prefix ? ' ' : '') + '@ ' : (prefix ? ', ' : '');
}

module.exports = init;<commit_msg>fix bug spotted by codacy<commit_after>'use strict';

var _ = require('lodash');
var moment = require('moment');
var times = require('../times');
var levels = require('../levels');
var timeago = require('./timeago')();

function init() {

  var openaps = {
    name: 'openaps'
    , label: 'OpenAPS'
    , pluginType: 'pill-status'
  };

  openaps.getPrefs = function getPrefs(sbx) {
    return {
      warn: sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 30,
      urgent: sbx.extendedSettings.urgent ? sbx.extendedSettings.urgent : 60,
      enableAlerts: sbx.extendedSettings.enableAlerts
    };
  };

  openaps.setProperties = function setProperties (sbx) {
    sbx.offerProperty('openaps', function setopenaps ( ) {
      var openapsStatus = _.findLast(sbx.data.devicestatus, function (status) {
        return sbx.entryMills(status) <= sbx.time && ('openaps' in status);
      });

      var loopStatus = checkLoopStatus(openapsStatus, sbx);
      openapsStatus = openapsStatus || {};
      openapsStatus.status = loopStatus;

      return openapsStatus;
    });
  };

  openaps.getEventTypes = function getEventTypes ( ) {
    return [
      {
        val: 'OpenAPS Offline'
        , name: 'OpenAPS Offline'
        , bg: false, insulin: false, carbs: false, prebolus: false, duration: true, percent: false, absolute: false, profile: false, split: false
      }
    ];
  };

  openaps.checkNotifications = function checkNotifications(sbx) {
    var prefs = openaps.getPrefs(sbx);

    if (!prefs.enableAlerts) { return; }

    var prop = sbx.properties.openaps;
    var ops = prepOps(prop, sbx);

    if (!ops.lastLoopTime) {
      console.info('OpenAPS hasn\'t reported a loop yet');
      return;
    }

    var now = moment();
    var level = statusLevel(ops, prefs, sbx);
    if (level >= levels.WARN) {
      sbx.notifications.requestNotify({
        level: level
        , title: 'OpenAPS isn\'t looping'
        , message: 'Last Loop: ' + formatAgo(ops.lastLoopTime, now.valueOf())
        , pushoverSound: 'echo'
        , plugin: openaps
        , debug: ops
      });
    }
  };

  openaps.updateVisualisation = function updateVisualisation (sbx) {
    var prop = sbx.properties.openaps;

    var info = [];

    info.push({label: timeFormat(prop.status.when, sbx), value: prop.status.label});

    var ops = prepOps(prop, sbx);
    var prefs = openaps.getPrefs(sbx);

    function valueString (prefix, value) {
      return value ? prefix + value : '';
    }

    function addSuggestion() {
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.suggestedTime, sbx)
        , value: [
          valueString('BG: ', ops.suggested.bg)
          , valueString(', ', ops.suggested.reason)
          , ops.suggested.mealAssist ? ' Meal Assist: ' + ops.suggested.mealAssist : ''
        ].join('')
      });
    }

    if ('enacted' === prop.status.code) {
      if (ops.suggestedTime.isAfter(ops.enactedTime)) {
        addSuggestion();
      }
      var canceled = ops.enacted.rate === 0 && ops.enacted.duration === 0;
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.enactedTime, sbx)
        , value: [
          valueString('BG: ', ops.enacted.bg)
          , ', Temp Basal' + (canceled ? ' Canceled' : ' Started') + ''
          , canceled ? '' : ' ' + ops.enacted.rate.toFixed(2) + ' for ' + ops.enacted.duration + 'm'
          , valueString(', ', ops.enacted.reason)
          , ops.enacted.mealAssist ? ' Meal Assist: ' + ops.enacted.mealAssist : ''
        ].join('')
      });
    } else if ('notenacted' === prop.status.code) {
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.notEnactedTime, sbx)
        , value: 'Not Enacted'
      });
    } else if ('looping' === prop.status.code) {
      addSuggestion();
    } else if (ops.lastLoopTime) {
      info.push({
        label: timeAt(false, sbx) + timeFormat(ops.lastLoopTime, sbx)
        , value: 'Last Loop'
      });
    }

    if (ops.iob && ops.iobTime.isAfter(ops.recent)) {
      var bolussnooze = ops.iob.bolussnooze || ops.iob.bolusiob;
      info.push({
        label: 'IOB'
        , value: [
          sbx.roundInsulinForDisplayFormat(ops.iob.iob) + 'U'
          , ops.iob.basaliob ? ', Basal IOB ' + sbx.roundInsulinForDisplayFormat(ops.iob.basaliob) + 'U' : ''
          , bolussnooze ? ', Bolus Snooze ' + sbx.roundInsulinForDisplayFormat(bolussnooze) + 'U' : ''
          , timeAt(true, sbx) + timeFormat(ops.iobTime, sbx)
        ].join('')
      });
    }

    if (ops.pumpTime && ops.pumpTime.isAfter(ops.recent)) {
      info.push({label: 'Last Pump Clock', value: ops.pumpTime.format('LT')});
    }

    sbx.pluginBase.updatePillText(openaps, {
      value: timeFormat(ops.lastLoopTime, sbx)
      , label: 'OpenAPS ' + prop.status.symbol
      , info: info
      , pillClass: statusClass(ops, prefs, sbx)
    });
  };

  return openaps;

}

function statusClass (ops, prefs, sbx) {
  var level = statusLevel(ops, prefs, sbx);
  var cls = 'current';

  if (level === levels.WARN) {
    cls = 'warn';
  } else if (level === levels.URGENT) {
    cls = 'urgent';
  }

  return cls;
}

function statusLevel (ops, prefs, sbx) {
  var level = levels.NONE;
  var now = moment(sbx.time);

  var offlineMarker = _.findLast(sbx.data.treatments, function match (treatment) {
    var eventTime = sbx.entryMills(treatment);
    var eventEnd = treatment.duration ? eventTime + times.mins(treatment.duration).msecs : eventTime;
    return eventTime <= sbx.time && treatment.eventType === 'OpenAPS Offline' && eventEnd >= sbx.time;
  });

  if (offlineMarker) {
    console.info('OpenAPS known offline, not checking for alerts');
  } else if (ops.lastLoopTime) {
    var urgentTime = ops.lastLoopTime.clone().add(prefs.urgent, 'minutes');
    var warningTime = ops.lastLoopTime.clone().add(prefs.warn, 'minutes');

    if (urgentTime.isBefore(now)) {
      level = levels.URGENT;
    } else if (warningTime.isBefore(now)) {
      level = levels.WARN;
    }
  }

  return level;
}

function checkLoopStatus (openapsStatus, sbx)  {

  var status = {
    symbol: '⚠'
    , code: 'warning'
    , label: 'Warning'
  };

  if (openapsStatus) {
    var enactedLast = openapsStatus.openaps.enacted && openapsStatus.openaps.enacted.recieved && moment(openapsStatus.openaps.enacted.timestamp);
    var notEnactedLast = openapsStatus.openaps.enacted && !openapsStatus.openaps.enacted.recieved && moment(openapsStatus.openaps.enacted.timestamp);
    var suggestedLast = openapsStatus.openaps.suggested && moment(openapsStatus.openaps.suggested.timestamp);

    var last =  moment(openapsStatus.mills);
    var recent = moment(sbx.time).subtract(15, 'minutes');

    if (notEnactedLast && notEnactedLast.isAfter(recent)) {
      status.symbol = 'x';
      status.code = 'notenacted';
      status.label = 'Not Enacted';
    } else if (enactedLast && enactedLast.isAfter(recent)) {
      status.symbol = '⌁';
      status.code = 'enacted';
      status.label = 'Enacted';
    } else if (suggestedLast && suggestedLast.isAfter(recent)) {
      status.symbol = '↻';
      status.code = 'looping';
      status.label = 'Looping';
    } else if (last && last.isAfter(recent)) {
      status.symbol = '◉';
      status.code = 'waiting';
      status.label = 'Waiting';
    }

    status.when = last;
  }

  return status;
}

function prepOps (prop, sbx) {

  var recent = moment(sbx.time).subtract(15, 'minutes');
  var iob = prop.openaps && prop.openaps.iob;
  var pump = prop.pump;
  var suggested = prop.openaps && prop.openaps.suggested;
  var suggestedTime = suggested && moment(suggested.timestamp);

  var enacted = null;
  var notEnacted = null;

  if (prop.openaps && prop.openaps.enacted && prop.openaps.enacted.recieved) {
    enacted = prop.openaps.enacted;
  }

  if (prop.openaps && !prop.openaps.enacted && prop.openaps.enacted.recieved) {
    notEnacted = prop.openaps.enacted;
  }

  var enactedTime = enacted && moment(enacted.timestamp);
  var notEnactedTime = notEnacted && moment(notEnacted.timestamp);

  return {
    recent: recent
    , suggested: suggested
    , suggestedTime: suggestedTime
    , enacted: enacted
    , enactedTime: enactedTime
    , notEnacted: notEnacted
    , notEnactedTime: notEnactedTime
    , iob: iob
    , iobTime: iob && moment(iob.timestamp)
    , pump: pump
    , pumpTime: pump && pump.clock && moment(pump.clock)
    , lastLoopTime: suggestedTime && enactedTime ? moment.max(suggestedTime, enactedTime) : enactedTime || suggestedTime
  };
}

function timeFormat (m, sbx) {

  var when;
  if (m && sbx.data.inRetroMode) {
    when = m.format('LT');
  } else if (m) {
    when = formatAgo(m, sbx.time);
  } else {
    when = 'unknown';
  }

  return when;
}

function formatAgo (m, nowMills) {
  var ago = timeago.calcDisplay({mills: m.valueOf()}, nowMills);
  return (ago.value ? ago.value : '') + ago.shortLabel + (ago.shortLabel.length === 1 ? ' ago' : '');
}

function timeAt (prefix, sbx) {
  return sbx.data.inRetroMode ? (prefix ? ' ' : '') + '@ ' : (prefix ? ', ' : '');
}

module.exports = init;<|endoftext|>


<commit_before>var myLatLng = {lat: -36.8576017, lng: 174.7590294};
var image = 'here.png';
var zoomAmount = 18;

var map = new google.maps.Map(document.getElementById('map'), {
	zoom: zoomAmount,
	center: myLatLng
});

var marker = new google.maps.Marker({
	position: myLatLng,
	map: map,
	icon: image
});

var infoWindow = new google.maps.InfoWindow({
	map: map,
	content: 'You are here'
});

function getFoodPlaces(){
	var service = new google.maps.places.PlacesService(map);
	service.nearbySearch({
		location: myLatLng,
		radius: 500,
		types: ['bakery', 'bar' , 'cafe','food',
		'grocery_or_supermarket', 'hospital', 'meal_delivery' , 'meal_takeaway',
		'restaurant' , 'school']
	}, createFoodMarker);
}

function createFoodMarker(results, status) {
	if (status === google.maps.places.PlacesServiceStatus.OK) {
		for (var i = 0; i < results.length; i++) {
			createMarker(results[i]);
		}
	}
}

function createMarker(place) {
	var placeLoc = place.geometry.location;
	var marker = new google.maps.Marker({
		position: place.geometry.location,
		map: map
	});

	google.maps.event.addListener(marker, 'click', function() {
		infowindow.setContent(place.name);
		infowindow.open(map, this);
	});
}

function initMap() {
	infowindow.open(map, marker);
	getFoodPlaces();
}

<commit_msg>corrected syntax error in mapscript<commit_after>var myLatLng = {lat: -36.8576017, lng: 174.7590294};
var image = 'here.png';
var zoomAmount = 18;
var map, marker, infoWindow;
var map = new google.maps.Map(document.getElementById('map'), {
	zoom: zoomAmount,
	center: myLatLng
});

var marker = new google.maps.Marker({
	position: myLatLng,
	map: map,
	icon: image
});

var infoWindow = new google.maps.InfoWindow({
	map: map,
	content: 'You are here'
});

function getFoodPlaces(){
	var service = new google.maps.places.PlacesService(map);
	service.nearbySearch({
		location: myLatLng,
		radius: 500,
		types: ['bakery', 'bar' , 'cafe','food',
		'grocery_or_supermarket', 'hospital', 'meal_delivery' , 'meal_takeaway',
		'restaurant' , 'school']
	}, createFoodMarker);
}

function createFoodMarker(results, status) {
	if (status === google.maps.places.PlacesServiceStatus.OK) {
		for (var i = 0; i < results.length; i++) {
			createMarker(results[i]);
		}
	}
}

function createMarker(place) {
	var placeLoc = place.geometry.location;
	var marker = new google.maps.Marker({
		position: place.geometry.location,
		map: map
	});

	google.maps.event.addListener(marker, 'click', function() {
		infowindow.setContent(place.name);
		infowindow.open(map, this);
	});
}

function initInfoWindow(){
	var infoWindow = new google.maps.InfoWindow({
		map: map,
		content: 'You are here'
	});
	infowindow.open(map, marker);
}

function initMarker(){
	marker = new google.maps.Marker({
		position: myLatLng,
		map: map,
		icon: image
	});
}

function initMap() {
	map = new google.maps.Map(document.getElementById('map'), {
		zoom: zoomAmount,
		center: myLatLng
	});

	initMarker();
	initInfoWindow();
	getFoodPlaces();
}

<|endoftext|>


<commit_before>var types = require('./types');
var api = require('./api');
var ParseError = require('./errors/parse');
var crc32 = require('buffer-crc32');
var defs = require('./definitions');

module.exports = class Parser {
  static encode(data, template, buffer, offset) {

    for(var i = 0; i < template.length; i++) {
      let entry = template[i];

      var key = Object.keys(entry);
      if(key.length !== 1) {
        throw new ParseError('Invalid api template');
      }
      key = key[0];
      if(!(key in data)) {
        throw new ParseError('Missing required field: ' + key);
      }

      switch(entry[key]) {
        case 'int32':
          offset = types.encodeInt32(data[key], buffer, offset);
          break;

        case 'int16':
          offset = types.encodeInt16(data[key], buffer, offset);
          break;

        case 'int64':
          offset = types.encodeInt64(data[key], buffer, offset);
          break;

        case 'int8':
          offset = types.encodeInt8(data[key], buffer, offset);
          break;

        case 'string':
          offset = types.encodeString(data[key], buffer, offset);
          break;

        case 'bytes':
          offset = types.encodeBytes(data[key], buffer, offset);
          break;

        case 'messageSet': {

          var globalOffset = offset + types.INT32_SIZE;
          var sizeEndOffset = globalOffset;
          var msgOffset = 0;
          data[key].forEach((message) => {

            let bodyStartOffset = msgOffset + api.Message.header_size;
            let bodyEndOffset = Parser.encode(
              {
                magicByte: api.Message.version,
                attributes: 0, // TODO: let this be passed in through message
                timestamp: new Date().getTime(),
                key: null,
                value: message.value
              },
              api.Message.body,
              buffer,
              bodyStartOffset + globalOffset
            ) - globalOffset;

            Parser.encode(
              {
                offset: 0,
                size: types.INT32_SIZE + bodyEndOffset - bodyStartOffset,
                crc: crc32.signed(buffer.slice(bodyStartOffset + globalOffset, bodyEndOffset + globalOffset))
              },
              api.Message.header,
              buffer,
              msgOffset + globalOffset
            ) - globalOffset;

            msgOffset = bodyEndOffset;
          });

          globalOffset += msgOffset;
          types.encodeInt32(globalOffset - sizeEndOffset, buffer, offset);
          offset = globalOffset;
          break;
        }

        case 'array':
          offset = types.encodeArraySize(data[key], buffer, offset);
          i++;
          data[key].forEach((row) => {
            offset = Parser.encode(row, template[i], buffer, offset);
          });
          break;

        default:
          throw new ParseError('Invalid encode type: ' + entry[key]);
      }
    }

    return offset;
  }

  static decode(template, buffer, offset) {
    var result = {};

    for(var i = 0; i < template.length; i++) {
      let entry = template[i];

      var key = Object.keys(entry);
      if(key.length !== 1) {
        throw new ParseError('Invalid api template');
      }
      key = key[0];

      switch(entry[key]) {
        case 'int32':
          [result[key], offset] = types.decodeInt32(buffer, offset);
          break;

        case 'int16':
          [result[key], offset] = types.decodeInt16(buffer, offset);
          break;

        case 'int64':
          [result[key], offset] = types.decodeInt64(buffer, offset);
          break;

        case 'int8':
          [result[key], offset] = types.decodeInt8(buffer, offset);
          break;

        case 'string':
          [result[key], offset] = types.decodeString(buffer, offset);
          break;

        case 'bytes':
          [result[key], offset] = types.decodeBytes(buffer, offset);
          break;

        case 'messageSet': {
          // Take care of byte formatting
          var size;
          [size, offset] = types.decodeInt32(buffer, offset);
          if(size <= 0) {
            result[key] = null;
            break;
          }

          let endOffset = offset + size;
          var messages = [];
          while(endOffset > offset) {
            // Start single message parsing
            let postCrcOffset = offset + api.Message.header_size;

            var message;
            [message, offset] = Parser.decode(api.Message.template, buffer, offset);

            if(crc32.signed(buffer.slice(postCrcOffset, offset)) !== message.crc) {
              throw new ParseError('Message CRC did not match calculated');
            }

            if(message.attributes !== 0) {
              throw new ParseError('Unsupported message encoding received');
            }

            message.value = message.value.toString();
            messages.push(message);
          }
          result[key] = messages;
          break;
        }

        case 'array': {
          result[key] = [];
          var length;
          [length, offset] = types.decodeArraySize(buffer, offset);
          i++;
          var value;
          for(var j = 0; j < length; j++) {
            [value, offset] = Parser.decode(template[i], buffer, offset);
            result[key].push(value);
          }
          break;
        }

        case 'error': {
          var errCode;
          [errCode, offset] = types.decodeInt16(buffer, offset);
          result[key] = defs.ERRORS[errCode + 1];
          break;
        }

        default:
          throw new ParseError('Invalid decode type: ' + entry[key]);
      }
    }
    return [result, offset];
  }
};
<commit_msg>add comment blocks to parser class<commit_after>var types = require('./types');
var api = require('./api');
var ParseError = require('./errors/parse');
var crc32 = require('buffer-crc32');
var defs = require('./definitions');

module.exports = class Parser {

  /**
  Parses an Object based on the template provided into a binary buffer
  Data object must contain the same keys in the same structure as the template
  The order of elements in the template array determines the order the corresponding data
  is encoded into the buffer
  Example Template/Data
  Template:
   [
     {apiKey: 'int16'},
     {version: 'int16'},
     {correlationId: 'int32'},
     {clientId: 'string'}
   ]

  Data:
   {
     apiKey: 0,
     version: 0,
     correlationId: 1
     clientId: 'test-client'
   }

  @param  Object data
  @param  Array  template
  @param  Buffer buffer
  @param  int    offset   where to start writing data in the buffer
  @return int    offset   offset after bytes written to buffer
  */
  static encode(data, template, buffer, offset) {

    for(var i = 0; i < template.length; i++) {
      let entry = template[i];

      var key = Object.keys(entry);
      if(key.length !== 1) {
        throw new ParseError('Invalid api template');
      }
      key = key[0];
      if(!(key in data)) {
        throw new ParseError('Missing required field: ' + key);
      }

      switch(entry[key]) {
        case 'int32':
          offset = types.encodeInt32(data[key], buffer, offset);
          break;

        case 'int16':
          offset = types.encodeInt16(data[key], buffer, offset);
          break;

        case 'int64':
          offset = types.encodeInt64(data[key], buffer, offset);
          break;

        case 'int8':
          offset = types.encodeInt8(data[key], buffer, offset);
          break;

        case 'string':
          offset = types.encodeString(data[key], buffer, offset);
          break;

        case 'bytes':
          offset = types.encodeBytes(data[key], buffer, offset);
          break;

        case 'messageSet': {

          var globalOffset = offset + types.INT32_SIZE;
          var sizeEndOffset = globalOffset;
          var msgOffset = 0;
          data[key].forEach((message) => {

            let bodyStartOffset = msgOffset + api.Message.header_size;
            let bodyEndOffset = Parser.encode(
              {
                magicByte: api.Message.version,
                attributes: 0, // TODO: let this be passed in through message
                timestamp: new Date().getTime(),
                key: null,
                value: message.value
              },
              api.Message.body,
              buffer,
              bodyStartOffset + globalOffset
            ) - globalOffset;

            Parser.encode(
              {
                offset: 0,
                size: types.INT32_SIZE + bodyEndOffset - bodyStartOffset,
                crc: crc32.signed(buffer.slice(bodyStartOffset + globalOffset, bodyEndOffset + globalOffset))
              },
              api.Message.header,
              buffer,
              msgOffset + globalOffset
            ) - globalOffset;

            msgOffset = bodyEndOffset;
          });

          globalOffset += msgOffset;
          types.encodeInt32(globalOffset - sizeEndOffset, buffer, offset);
          offset = globalOffset;
          break;
        }

        case 'array':
          offset = types.encodeArraySize(data[key], buffer, offset);
          i++;
          data[key].forEach((row) => {
            offset = Parser.encode(row, template[i], buffer, offset);
          });
          break;

        default:
          throw new ParseError('Invalid encode type: ' + entry[key]);
      }
    }

    return offset;
  }

  /**
  Parses a binary buffer into a complex object based on the template provided
  The order of elements in the template array determines the order of data parsed from the
  buffer
  @param object template
  @param Buffer buffer
  @param int    offset
  */
  static decode(template, buffer, offset) {
    var result = {};

    for(var i = 0; i < template.length; i++) {
      let entry = template[i];

      var key = Object.keys(entry);
      if(key.length !== 1) {
        throw new ParseError('Invalid api template');
      }
      key = key[0];

      switch(entry[key]) {
        case 'int32':
          [result[key], offset] = types.decodeInt32(buffer, offset);
          break;

        case 'int16':
          [result[key], offset] = types.decodeInt16(buffer, offset);
          break;

        case 'int64':
          [result[key], offset] = types.decodeInt64(buffer, offset);
          break;

        case 'int8':
          [result[key], offset] = types.decodeInt8(buffer, offset);
          break;

        case 'string':
          [result[key], offset] = types.decodeString(buffer, offset);
          break;

        case 'bytes':
          [result[key], offset] = types.decodeBytes(buffer, offset);
          break;

        case 'messageSet': {
          // Take care of byte formatting
          var size;
          [size, offset] = types.decodeInt32(buffer, offset);
          if(size <= 0) {
            result[key] = null;
            break;
          }

          let endOffset = offset + size;
          var messages = [];
          while(endOffset > offset) {
            // Start single message parsing
            let postCrcOffset = offset + api.Message.header_size;

            var message;
            [message, offset] = Parser.decode(api.Message.template, buffer, offset);

            if(crc32.signed(buffer.slice(postCrcOffset, offset)) !== message.crc) {
              throw new ParseError('Message CRC did not match calculated');
            }

            if(message.attributes !== 0) {
              throw new ParseError('Unsupported message encoding received');
            }

            message.value = message.value.toString();
            messages.push(message);
          }
          result[key] = messages;
          break;
        }

        case 'array': {
          result[key] = [];
          var length;
          [length, offset] = types.decodeArraySize(buffer, offset);
          i++;
          var value;
          for(var j = 0; j < length; j++) {
            [value, offset] = Parser.decode(template[i], buffer, offset);
            result[key].push(value);
          }
          break;
        }

        case 'error': {
          var errCode;
          [errCode, offset] = types.decodeInt16(buffer, offset);
          result[key] = defs.ERRORS[errCode + 1];
          break;
        }

        default:
          throw new ParseError('Invalid decode type: ' + entry[key]);
      }
    }
    return [result, offset];
  }
};
<|endoftext|>


<commit_before>var BufferResponse = require('express-buffer-response');
var onHeaders = require('on-headers');
var pathRegexp = require('path-to-regexp');
var URL = require('url');
//var CacheDebounce = require('cache-debounce');
var debug = require('debug')('raja:express');

module.exports = ExpressProxy;

function ExpressProxy(raja, opts) {
	if (!(this instanceof ExpressProxy)) return new ExpressProxy(raja, opts);
	this.raja = raja;
	this.opts = opts || {};
	this.middleware = this.middleware.bind(this);
}

//var GetMw = CacheDebounce(function(url, baseUrl, req, res, next, cb) {
var GetMw = function(url, baseUrl, req, res, next, cb) {
	var raja = this.raja;
	res.set('X-Raja', raja.opts.namespace);
	raja.retrieve(url, res, function(err, resource) {
		if (err) raja.error(err); // fall through
		if (resource && resource.valid) {
			debug('found valid', resource.key, resource.headers);
			for (var name in resource.headers) {
				if (name in {'Content-Type':1, 'ETag':1, 'Vary':1, 'Content-Encoding':1, 'X-Grant': 1, 'X-Raja':1}) {
					res.set(name, resource.headers[name]);
				}
			}
			var ETag = resource.headers.ETag;
			if (ETag && req.get('If-None-Match') == ETag) {
				res.sendStatus(304);
			} else {
				if (resource.headers['X-Grant']) {
					res.set('Cache-Control', 'max-age=0,must-revalidate,private,no-cache');
					res.set('Pragma', 'no-cache');
				}
				if (resource.mtime) {
					res.set('Last-Modified', resource.mtime.toUTCString());
				}
				res.send(resource.data);
			}
			cb();
		} else {
			if (!resource) {
				debug('no resource found', url);
				resource = raja.create({url: url, builder: 'express'}, res);
			} else {
				debug('found invalid resource', resource.key);
			}
			req.resource = resource;
			onHeaders(res, function() {
				var lastMod = res.get('Last-Modified');
				if (lastMod) {
					lastMod = new Date(lastMod);
					if (isNaN(lastMod.getTime())) lastMod = null;
				}
				if (!lastMod) {
					lastMod = new Date();
				}
				if (resource.headers['X-Grant']) {
					res.set('Cache-Control', 'max-age=0,must-revalidate,private,no-cache');
					res.set('Pragma', 'no-cache');
				}
				res.set('Last-Modified', lastMod.toUTCString());
				resource.mtime = lastMod;
			});

			BufferResponse(res, function(err, bufl) {
				delete req.resource;
				if (err) return cb(err);
				// not sure we must ignore codes above 300 but what to do with them ?
				if (res.statusCode >= 200 && res.statusCode < 300) {
					resource.headers = raja.headers(res);
					debug('cache response', res.statusCode, url, resource.headers);
					if (url != baseUrl && isResJson(res)) {
						debug("url with query depends on baseUrl", url, baseUrl);
						// assume same type
						var depHeaders = {};
						for (var name in resource.headers) {
							if (name in {'Vary':1, 'Content-Type':1, 'X-Raja':1}) {
								depHeaders[name] = resource.headers[name];
							}
						}
						resource.depend({url: baseUrl, headers: depHeaders, builder: 'express'});
					}
					resource.code = res.statusCode;
					resource.data = bufl.slice();
					resource.valid = true;
					resource.save();
				}
				cb();
			}.bind(this));
			next();
		}
	}.bind(this));
};
//}, function(url) {
//	return url;
//});

ExpressProxy.prototype.middleware = function(req, res, next) {
	var raja = this.raja;
	var method = req.method.toLowerCase();
	var baseUrl = req.protocol + "://" + req.get('Host');
	var url = baseUrl + req.url;
	baseUrl += req.path;

	if (this.opts.disable) {
		req.resource = raja.create({url: url, builder: 'express'}, res);
		return next();
	}

	if (method == "get") {
		GetMw.call(this, url, baseUrl, req, res, next, function(err) {
			if (err) console.error(err);
		});
	} else if (method == "purge") {
		res.set('X-Raja', raja.opts.namespace);
		raja.retrieve(url, res, function(err, resource) {
			if (err) return next(err);
			if (!resource) return next(404);
			function finish(err) {
				if (err) console.error(err);
				invalidateAndSend(raja, {
					key: raja.reskey(url, req),
					method: method,
					mtime: new Date()
				});
				res.sendStatus(200);
			}
			if (resource.page && raja.opts.dom) raja.opts.dom.pool.release(resource.page, finish);
			else finish();
		});
	} else {
		// must be done before because req.params changes
		var coll = collectionInfo(req.route.path, url, req.params);
		BufferResponse(res, function(err, bufl) {
			if (err) return raja.error(err);
			if (res.statusCode < 200 || res.statusCode >= 400) return;
			var now = new Date(); // TODO inspect HTTP response headers like Date, Last-Modified
			// data is response buffer or request body, in that order
			var data = bufl;
			if (method != "delete" && isResJson(res) && bufl && bufl.length) {
				data = JSON.parse(bufl.toString());
			} else if (isReqJson(req) && req.body) {
				data = req.body;
			}

			var headers = raja.headers(res);
			headers['X-Raja'] = raja.opts.namespace;
			if (method == "put" && !(coll && coll.url == url)) {
				// send the message about the element if the url concerns an element
				// and the method is PUT.
				invalidateAndSend(raja, {
					url: url,
					method: method,
					mtime: now,
					data: data
				}, headers);
			}
			if (coll) {
				if (method == "post" && res.get('Location')) {
					// obtain coll.value from matching loc against req.route.path
					coll.value = lastParam(req.route.path, res.get('Location'), coll.name);
				}
				if (coll.value !== undefined) {
					// either promote a DELETE element method to a collection method,
					// or integrate coll.name into a PUT element method data
					if (!data) data = {};
					if (data[coll.name] === undefined) data[coll.name] = coll.value;
				}
				invalidateAndSend(raja, {
					url: coll.url,
					method: method,
					mtime: now,
					data: ensureArray(data)
				}, headers);
			} else if (method == "post") {
				debug(url, "a POST to a non-collection route is not correct, invalidating anyway");
				invalidateAndSend(raja, {
					url: url,
					method: method,
					mtime: now,
					data: ensureArray(data)
				}, headers);
			}
		});
		next();
	}
};

function isResJson(res) {
	return res.req.is.call({headers: {
		'transfer-encoding': true,
		'content-length': 0,
		'content-type': res.get('Content-Type')
	}}, "json");
}

function isReqJson(req) {
	var type = req.get('Content-Type') || req.get('Accept') || '';
	return req.is('json') || type.indexOf('/json') > 0;
}

function collectionInfo(routePath, url, params) {
	var find = /^:(.+)\?$/.exec(routePath.split('/').pop());
	if (find != null && params.hasOwnProperty(find[1])) {
		var name = find[1];
		var value = params[name];
		if (value !== undefined) {
			url = url.split('/');
			url.pop();
			url = url.join('/');
		}
		return {url: url, name: name, value: value};
	} else {
		return;
	}
}

function lastParam(routePath, url, param) {
	var keys = [];
	var regexp = pathRegexp(routePath, keys);
	var m = regexp.exec(URL.parse(url).pathname);
	if (!m) return;
	var val = m[m.length-1];
	var key = keys[keys.length-1];
	if (key.name != param) return;
	if (typeof val == 'string') {
		try {	val = decodeURIComponent(val); } catch (e) { val = undefined; }
	}
	return val;
}

function ensureArray(data) {
	if (!data || data.length == 0) {
		// empty
		data = [];
	} else if (Array.isArray(data)) {
		// all right, do nothing
	} else if (typeof data == "string") {
		// pure strings
		if (data[0] == '{') data = '[' + data + ']';
	} else if (typeof data.slice == "function") {
		// Buffers, bl-buffers
		if (data.slice(0, 1).toString() == '{') data = '[' + data.toString() + ']';
	} else if (typeof data == "object") {
		// pure objects
		data = [data];
	}
	return data;
}

function invalidateAndSend(raja, msg, headers) {
	if (!msg.key) {
		msg.key = raja.reskey({url:msg.url, headers: headers});
		delete msg.url;
	}
	debug("invalidate and send", msg.key);
	raja.store.invalidate(msg.key, function(err) {
		if (err) return raja.error(err);
		raja.send(msg);
	});
}

<commit_msg>Fix ETag caching<commit_after>var BufferResponse = require('express-buffer-response');
var onHeaders = require('on-headers');
var pathRegexp = require('path-to-regexp');
var URL = require('url');
//var CacheDebounce = require('cache-debounce');
var debug = require('debug')('raja:express');

module.exports = ExpressProxy;

function ExpressProxy(raja, opts) {
	if (!(this instanceof ExpressProxy)) return new ExpressProxy(raja, opts);
	this.raja = raja;
	this.opts = opts || {};
	this.middleware = this.middleware.bind(this);
}

//var GetMw = CacheDebounce(function(url, baseUrl, req, res, next, cb) {
var GetMw = function(url, baseUrl, req, res, next, cb) {
	var raja = this.raja;
	res.set('X-Raja', raja.opts.namespace);
	raja.retrieve(url, res, function(err, resource) {
		if (err) raja.error(err); // fall through
		if (resource && resource.valid) {
			debug('found valid', resource.key, resource.headers);
			for (var name in resource.headers) {
				if (name in {'Content-Type':1, 'ETag':1, 'Vary':1, 'Content-Encoding':1, 'X-Grant': 1, 'X-Raja':1}) {
					res.set(name, resource.headers[name]);
				}
			}
			var ETag = resource.headers.ETag;
			if (ETag && req.get('If-None-Match') == ETag) {
				res.sendStatus(304);
			} else {
				if (resource.headers['X-Grant']) {
					res.set('Cache-Control', 'max-age=0,must-revalidate,private,no-cache');
					res.set('Pragma', 'no-cache');
				}
				if (resource.mtime) {
					res.set('Last-Modified', resource.mtime.toUTCString());
				}
				res.send(resource.data);
			}
			cb();
		} else {
			if (!resource) {
				debug('no resource found', url);
				resource = raja.create({url: url, builder: 'express'}, res);
			} else {
				debug('found invalid resource', resource.key);
			}
			req.resource = resource;
			var curETag;
			onHeaders(res, function() {
				var etag = res.get('ETag');
				if (etag && !res.statusCode == 304) {
					curETag = etag;
					res.set('ETag', '');
				}
				var lastMod = res.get('Last-Modified');
				if (lastMod) {
					lastMod = new Date(lastMod);
					if (isNaN(lastMod.getTime())) lastMod = null;
				}
				if (!lastMod) {
					lastMod = new Date();
				}
				if (resource.headers['X-Grant']) {
					res.set('Cache-Control', 'max-age=0,must-revalidate,private,no-cache');
					res.set('Pragma', 'no-cache');
				}
				res.set('Last-Modified', lastMod.toUTCString());
				resource.mtime = lastMod;
			});

			BufferResponse(res, function(err, bufl) {
				delete req.resource;
				if (err) return cb(err);
				// not sure we must ignore codes above 300 but what to do with them ?
				if (res.statusCode >= 200 && res.statusCode < 300) {
					resource.headers = raja.headers(res);
					if (curETag) resource.headers.ETag = curETag;
					resource.code = res.statusCode;
					resource.data = bufl.slice();
					resource.valid = true;
					debug('cache response', res.statusCode, url, resource.headers);
					if (url != baseUrl && isResJson(res)) {
						debug("url with query depends on baseUrl", url, baseUrl);
						// assume same type
						var depHeaders = {};
						for (var name in resource.headers) {
							if (name in {'Vary':1, 'Content-Type':1, 'X-Raja':1}) {
								depHeaders[name] = resource.headers[name];
							}
						}
						resource.depend({url: baseUrl, headers: depHeaders, builder: 'express'});
					}
					resource.save();
				} else {
					debug("response not cached because of statusCode", url, res.statusCode);
				}
				cb();
			}.bind(this));
			next();
		}
	}.bind(this));
};
//}, function(url) {
//	return url;
//});

ExpressProxy.prototype.middleware = function(req, res, next) {
	var raja = this.raja;
	var method = req.method.toLowerCase();
	var baseUrl = req.protocol + "://" + req.get('Host');
	var url = baseUrl + req.url;
	baseUrl += req.path;

	if (this.opts.disable) {
		req.resource = raja.create({url: url, builder: 'express'}, res);
		return next();
	}

	if (method == "get") {
		GetMw.call(this, url, baseUrl, req, res, next, function(err) {
			if (err) console.error(err);
		});
	} else if (method == "purge") {
		res.set('X-Raja', raja.opts.namespace);
		raja.retrieve(url, res, function(err, resource) {
			if (err) return next(err);
			if (!resource) return next(404);
			function finish(err) {
				if (err) console.error(err);
				invalidateAndSend(raja, {
					key: raja.reskey(url, req),
					method: method,
					mtime: new Date()
				});
				res.sendStatus(200);
			}
			if (resource.page && raja.opts.dom) raja.opts.dom.pool.release(resource.page, finish);
			else finish();
		});
	} else {
		// must be done before because req.params changes
		var coll = collectionInfo(req.route.path, url, req.params);
		BufferResponse(res, function(err, bufl) {
			if (err) return raja.error(err);
			if (res.statusCode < 200 || res.statusCode >= 400) return;
			var now = new Date(); // TODO inspect HTTP response headers like Date, Last-Modified
			// data is response buffer or request body, in that order
			var data = bufl;
			if (method != "delete" && isResJson(res) && bufl && bufl.length) {
				data = JSON.parse(bufl.toString());
			} else if (isReqJson(req) && req.body) {
				data = req.body;
			}

			var headers = raja.headers(res);
			headers['X-Raja'] = raja.opts.namespace;
			if (method == "put" && !(coll && coll.url == url)) {
				// send the message about the element if the url concerns an element
				// and the method is PUT.
				invalidateAndSend(raja, {
					url: url,
					method: method,
					mtime: now,
					data: data
				}, headers);
			}
			if (coll) {
				if (method == "post" && res.get('Location')) {
					// obtain coll.value from matching loc against req.route.path
					coll.value = lastParam(req.route.path, res.get('Location'), coll.name);
				}
				if (coll.value !== undefined) {
					// either promote a DELETE element method to a collection method,
					// or integrate coll.name into a PUT element method data
					if (!data) data = {};
					if (data[coll.name] === undefined) data[coll.name] = coll.value;
				}
				invalidateAndSend(raja, {
					url: coll.url,
					method: method,
					mtime: now,
					data: ensureArray(data)
				}, headers);
			} else if (method == "post") {
				debug(url, "a POST to a non-collection route is not correct, invalidating anyway");
				invalidateAndSend(raja, {
					url: url,
					method: method,
					mtime: now,
					data: ensureArray(data)
				}, headers);
			}
		});
		next();
	}
};

function isResJson(res) {
	return res.req.is.call({headers: {
		'transfer-encoding': true,
		'content-length': 0,
		'content-type': res.get('Content-Type')
	}}, "json");
}

function isReqJson(req) {
	var type = req.get('Content-Type') || req.get('Accept') || '';
	return req.is('json') || type.indexOf('/json') > 0;
}

function collectionInfo(routePath, url, params) {
	var find = /^:(.+)\?$/.exec(routePath.split('/').pop());
	if (find != null && params.hasOwnProperty(find[1])) {
		var name = find[1];
		var value = params[name];
		if (value !== undefined) {
			url = url.split('/');
			url.pop();
			url = url.join('/');
		}
		return {url: url, name: name, value: value};
	} else {
		return;
	}
}

function lastParam(routePath, url, param) {
	var keys = [];
	var regexp = pathRegexp(routePath, keys);
	var m = regexp.exec(URL.parse(url).pathname);
	if (!m) return;
	var val = m[m.length-1];
	var key = keys[keys.length-1];
	if (key.name != param) return;
	if (typeof val == 'string') {
		try {	val = decodeURIComponent(val); } catch (e) { val = undefined; }
	}
	return val;
}

function ensureArray(data) {
	if (!data || data.length == 0) {
		// empty
		data = [];
	} else if (Array.isArray(data)) {
		// all right, do nothing
	} else if (typeof data == "string") {
		// pure strings
		if (data[0] == '{') data = '[' + data + ']';
	} else if (typeof data.slice == "function") {
		// Buffers, bl-buffers
		if (data.slice(0, 1).toString() == '{') data = '[' + data.toString() + ']';
	} else if (typeof data == "object") {
		// pure objects
		data = [data];
	}
	return data;
}

function invalidateAndSend(raja, msg, headers) {
	if (!msg.key) {
		msg.key = raja.reskey({url:msg.url, headers: headers});
		delete msg.url;
	}
	debug("invalidate and send", msg.key);
	raja.store.invalidate(msg.key, function(err) {
		if (err) return raja.error(err);
		raja.send(msg);
	});
}

<|endoftext|>


<commit_before>var BufferResponse = require('express-buffer-response');
var queue = require('async-queue');

module.exports = ExpressProxy;

function ExpressProxy(raja, opts) {
	if (!(this instanceof ExpressProxy)) return new ExpressProxy(raja, opts);
	this.raja = raja;
	this.opts = opts || {};
	this.middleware = this.middleware.bind(this);
}

ExpressProxy.prototype.middleware = function(req, res, next) {
	if (this.opts.filter && this.opts.filter(req) == false) return next();
	var url = req.protocol + "://" + req.get('Host') + req.url;
	var raja = this.raja;
	if (req.method == "GET") {
		this.raja.store.get(url, function(err, resource) {
			if (err) raja.error(err); // fall through
			if (resource && resource.valid) {
				res.set('Last-Modified', resource.mtime.toUTCString());
				if (resource.mime) res.type(resource.mime);
				res.send(resource.data);
			} else {
				BufferResponse(res, function(err, bufl) {
					if (err) return console.error(err); // or just return if already logged
					this.finished(url, res.statusCode, res.get('Content-Type'), bufl.slice());
				}.bind(this));
				res.set('Last-Modified', (new Date()).toUTCString());
				next();
			}
		}.bind(this));
	} else {
		// must be done before because req.params changes
		var collectionUrl = resourcePath(req.route.path, url, req.params);
		BufferResponse(res, function(err, buf) {
			if (err) return raja.error(err);
			if (res.statusCode < 200 || res.statusCode >= 400) return;
			var msg = {
				method: req.method.toLowerCase(),
				mtime: Date.now()
			};
			if (req.is("json") && req.body) msg.data = req.body;
			if (res.get('Location')) url = res.get('Location');
			msg.url = url;
			invalidateAndSend(raja, url, msg);
			if (collectionUrl) {
				// matches the GET request on this collection
				var cmsg = shallow(msg);
				cmsg.data = [msg.data];
				cmsg.url = collectionUrl;
				invalidateAndSend(raja, collectionUrl, cmsg);
			}
		});
		next();
	}
};

ExpressProxy.prototype.finished = function(url, code, mime, buf) {
	this.raja.store.set(url, {
		code: code,
		data: buf,
		mime: mime
	}, this.raja.error);
};

function resourcePath(routePath, url, params) {
	var find = /^:(.+)\?$/.exec(routePath.split('/').pop());
	if (find != null && params[find[1]] !== undefined) {
		url = url.split('/');
		url.pop();
		url = url.join('/');
		return url;
	} else {
		return;
	}
}

function invalidateAndSend(raja, url, msg) {
	raja.store.invalidate(url, function(err) {
		if (err) return raja.error(err);
		raja.send(msg);
	});
}

function shallow(src) {
	var dst = {};
	for (var key in src) dst[key] = src[key];
	return dst;
}
<commit_msg>Better detection of collection url<commit_after>var BufferResponse = require('express-buffer-response');
var queue = require('async-queue');

module.exports = ExpressProxy;

function ExpressProxy(raja, opts) {
	if (!(this instanceof ExpressProxy)) return new ExpressProxy(raja, opts);
	this.raja = raja;
	this.opts = opts || {};
	this.middleware = this.middleware.bind(this);
}

ExpressProxy.prototype.middleware = function(req, res, next) {
	if (this.opts.filter && this.opts.filter(req) == false) return next();
	var url = req.protocol + "://" + req.get('Host') + req.url;
	var raja = this.raja;
	if (req.method == "GET") {
		this.raja.store.get(url, function(err, resource) {
			if (err) raja.error(err); // fall through
			if (resource && resource.valid) {
				res.set('Last-Modified', resource.mtime.toUTCString());
				if (resource.mime) res.type(resource.mime);
				res.send(resource.data);
			} else {
				BufferResponse(res, function(err, bufl) {
					if (err) return console.error(err); // or just return if already logged
					this.finished(url, res.statusCode, res.get('Content-Type'), bufl.slice());
				}.bind(this));
				res.set('Last-Modified', (new Date()).toUTCString());
				next();
			}
		}.bind(this));
	} else {
		// must be done before because req.params changes
		var collectionUrl = resourcePath(req.route.path, url, req.params);
		BufferResponse(res, function(err, buf) {
			if (err) return raja.error(err);
			if (res.statusCode < 200 || res.statusCode >= 400) return;
			var msg = {
				method: req.method.toLowerCase(),
				mtime: Date.now()
			};
			if (req.is("json") && req.body) msg.data = req.body;
			if (res.get('Location')) url = res.get('Location');
			msg.url = url;
			invalidateAndSend(raja, url, msg);
			if (collectionUrl) {
				// matches the GET request on this collection
				var cmsg = shallow(msg);
				cmsg.data = [msg.data];
				cmsg.url = collectionUrl;
				invalidateAndSend(raja, collectionUrl, cmsg);
			}
		});
		next();
	}
};

ExpressProxy.prototype.finished = function(url, code, mime, buf) {
	this.raja.store.set(url, {
		code: code,
		data: buf,
		mime: mime
	}, this.raja.error);
};

function resourcePath(routePath, url, params) {
	var find = /^:(.+)\?$/.exec(routePath.split('/').pop());
	if (find != null && params.hasOwnProperty(find[1])) {
		if (params[find[1]] !== undefined) {
			url = url.split('/');
			url.pop();
			url = url.join('/');
		}
		return url;
	} else {
		return;
	}
}

function invalidateAndSend(raja, url, msg) {
	raja.store.invalidate(url, function(err) {
		if (err) return raja.error(err);
		raja.send(msg);
	});
}

function shallow(src) {
	var dst = {};
	for (var key in src) dst[key] = src[key];
	return dst;
}
<|endoftext|>


<commit_before>var BufferResponse = require('express-buffer-response');
var queue = require('async-queue');
var pathRegexp = require('path-to-regexp');
var URL = require('url');

module.exports = ExpressProxy;

function ExpressProxy(raja, opts) {
	if (!(this instanceof ExpressProxy)) return new ExpressProxy(raja, opts);
	this.raja = raja;
	this.opts = opts || {};
	this.middleware = this.middleware.bind(this);
	this.remote = raja.proxies.remote();
}

ExpressProxy.prototype.middleware = function(req, res, next) {
	if (this.opts.filter && this.opts.filter(req) == false) return next();
	var url = req.protocol + "://" + req.get('Host') + req.url;
	var raja = this.raja;
	if (req.method == "GET") {
		this.raja.store.get(url, function(err, resource) {
			if (err) raja.error(err); // fall through
			res.set('X-Raja', raja.opts.namespace);
			if (resource && resource.valid) {
				res.set('Last-Modified', resource.mtime.toUTCString());
				if (resource.mime) res.type(resource.mime);
				res.send(resource.data);
			} else {
				var resources = {__notcalled__: true};
				req.getResource = getResource.bind(this, url, resources);
				BufferResponse(res, function(err, bufl) {
					delete req.getResource;
					if (resources.__notcalled__) resources = undefined;
					if (err) return console.error(err); // or just return if already logged
					this.finished(url, res.statusCode, res.get('Content-Type'), bufl.slice(), resources);
				}.bind(this));
				res.set('Last-Modified', (new Date()).toUTCString());
				next();
			}
		}.bind(this));
	} else {
		// must be done before because req.params changes
		var coll = collectionInfo(req.route.path, url, req.params);
		BufferResponse(res, function(err, bufl) {
			if (err) return raja.error(err);
			if (res.statusCode < 200 || res.statusCode >= 400) return;
			var method = req.method.toLowerCase();
			var now = Date.now(); // TODO inspect HTTP response headers like Date, Last-Modified
			// data is response buffer or request body, in that order
			var data;
			if (res.get('Content-Type') == "application/json" && bufl && bufl.length) {
				data = bufl;
			} else if (req.is("json") && req.body) {
				data = req.body;
			}
			var msg = { method: method, mtime: Date.now() };
			if (method == "put" && !(coll && coll.url == url)) {
				// send the message about the element if the url concerns an element
				// and the method is PUT.
				invalidateAndSend(raja, {
					url: url,
					method: method,
					mtime: now,
					data: data
				});
			}
			if (coll) {
				if (method == "post" && res.get('Location')) {
					// obtain coll.value from matching loc against req.route.path
					coll.value = lastParam(req.route.path, res.get('Location'), coll.name);
				}
				if (coll.value !== undefined) {
					// either promote a DELETE element method to a collection method,
					// or integrate coll.name into a PUT element method data
					if (!data) data = {};
					if (data[coll.name] === undefined) data[coll.name] = coll.value;
				}
				invalidateAndSend(raja, {
					url: coll.url,
					method: method,
					mtime: now,
					data: ensureArray(data)
				});
			}
		});
		next();
	}
};

ExpressProxy.prototype.finished = function(url, code, mime, buf, resources) {
	this.raja.store.set(url, {
		code: code,
		data: buf,
		mime: mime,
		resources: resources && Object.keys(resources)
	}, this.raja.error);
};

function collectionInfo(routePath, url, params) {
	var find = /^:(.+)\?$/.exec(routePath.split('/').pop());
	if (find != null && params.hasOwnProperty(find[1])) {
		var name = find[1];
		var value = params[name];
		if (value !== undefined) {
			url = url.split('/');
			url.pop();
			url = url.join('/');
		}
		return {url: url, name: name, value: value};
	} else {
		return;
	}
}

function lastParam(routePath, url, param) {
	var keys = [];
	var regexp = pathRegexp(routePath, keys);
	var m = regexp.exec(URL.parse(url).pathname);
	if (!m) return;
	var val = m[m.length-1];
	var key = keys[keys.length-1];
	if (key.name != param) return;
	if (typeof val == 'string') {
		try {	val = decodeURIComponent(val); } catch (e) { val = undefined; }
	}
	return val;
}

function ensureArray(data) {
	if (!data || data.length == 0) {
		// empty
		data = [];
	} else if (Array.isArray(data)) {
		// all right, do nothing
	} else if (typeof data == "string") {
		// pure strings
		if (data[0] == '{') data = '[' + data + ']';
	} else if (typeof data.slice == "function") {
		// Buffers, bl-buffers
		if (data.slice(0, 1).toString() == '{') data = '[' + data.toString() + ']';
	} else if (typeof data == "object") {
		// pure objects
		data = [data];
	}
	return data;
}

function invalidateAndSend(raja, msg) {
	raja.store.invalidate(msg.url, function(err) {
		if (err) return raja.error(err);
		raja.send(msg);
	});
}

function getResource(referer, resources, remote, query, cb) {
	delete resources.__notcalled__;
	if (!cb && typeof query == "function") {
		cb = query;
		query = null;
	}
	if (query) {
		remote = urlParams(remote, query);
		remote = urlQuery(remote, query);
	}
	if (!/^https?:/.test(remote)) remote = absolute(URL.parse(referer), remote);
	this.remote.get(remote, function(err, data) {
		if (err >= 400 && err < 500) delete resources[remote];
		else if (!err) resources[remote] = true;
		cb(err, data);
	});
}

function absolute(loc, url) {
	if (/^https?/i.test(url)) return url;
	var path = loc.pathname;
	if (url.indexOf('..') == 0) {
		path = path.split('/');
		path.pop();
		url = path.join('/') + url.substring(2);
	} else if (url == '.') {
		return loc.href;
	} else if (url.indexOf('.') == 0) {
		url = path + url.substring(1);
	} else if (url.indexOf('/') != 0) {
		var base = path.split('/');
		base.pop();
		base = base.join('/');
		url = base + '/' + url;
	}
	url = loc.protocol + '//' + loc.host + url;
	return url;
}

function urlParams(url, params) {
	if (!params) return url;
	return url.replace(/\/:(\w+)/g, function(str, name) {
		var val = params[name];
		if (val != null) {
			delete params[name];
			return '/' + val;
		} else {
			return '/:' + name;
		}
	});
}

function urlQuery(url, query) {
	if (!query) return url;
	var comps = [];
	var str;
	for (var k in query) {
		str = encodeURIComponent(k);
		if (query[k] != null) str += '=' + encodeURIComponent(query[k]);
		comps.push(str);
	}
	if (comps.length) {
		if (url.indexOf('?') > 0) url += '&';
		else url += '?';
		url += comps.join('&');
	}
	return url;
}

<commit_msg>Declare url?query depends on url in express proxy<commit_after>var BufferResponse = require('express-buffer-response');
var queue = require('async-queue');
var pathRegexp = require('path-to-regexp');
var URL = require('url');

module.exports = ExpressProxy;

function ExpressProxy(raja, opts) {
	if (!(this instanceof ExpressProxy)) return new ExpressProxy(raja, opts);
	this.raja = raja;
	this.opts = opts || {};
	this.middleware = this.middleware.bind(this);
	this.remote = raja.proxies.remote();
}

ExpressProxy.prototype.middleware = function(req, res, next) {
	if (this.opts.filter && this.opts.filter(req) == false) return next();
	var xurl = req.protocol + "://" + req.get('Host');
	var url = xurl + req.path;
	xurl += req.url;
	var raja = this.raja;
	if (req.method == "GET") {
		this.raja.store.get(xurl, function(err, resource) {
			if (err) raja.error(err); // fall through
			res.set('X-Raja', raja.opts.namespace);
			if (resource && resource.valid) {
				res.set('Last-Modified', resource.mtime.toUTCString());
				if (resource.mime) res.type(resource.mime);
				res.send(resource.data);
			} else {
				var resources = {__notcalled__: true};
				req.getResource = getResource.bind(this, url, resources);
				BufferResponse(res, function(err, bufl) {
					delete req.getResource;
					if (err) return console.error(err); // or just return if already logged
					if (url != xurl) {
						resources[url] = true;
						delete resources.__notcalled__;
					}
					if (resources.__notcalled__) {
						resources = undefined;
					}
					this.finished(xurl, res.statusCode, res.get('Content-Type'), bufl.slice(), resources);
				}.bind(this));
				res.set('Last-Modified', (new Date()).toUTCString());
				next();
			}
		}.bind(this));
	} else {
		// must be done before because req.params changes
		var coll = collectionInfo(req.route.path, url, req.params);
		BufferResponse(res, function(err, bufl) {
			if (err) return raja.error(err);
			if (res.statusCode < 200 || res.statusCode >= 400) return;
			var method = req.method.toLowerCase();
			var now = Date.now(); // TODO inspect HTTP response headers like Date, Last-Modified
			// data is response buffer or request body, in that order
			var data;
			if (res.get('Content-Type') == "application/json" && bufl && bufl.length) {
				data = bufl;
			} else if (req.is("json") && req.body) {
				data = req.body;
			}
			var msg = { method: method, mtime: Date.now() };
			if (method == "put" && !(coll && coll.url == url)) {
				// send the message about the element if the url concerns an element
				// and the method is PUT.
				invalidateAndSend(raja, {
					url: url,
					method: method,
					mtime: now,
					data: data
				});
			}
			if (coll) {
				if (method == "post" && res.get('Location')) {
					// obtain coll.value from matching loc against req.route.path
					coll.value = lastParam(req.route.path, res.get('Location'), coll.name);
				}
				if (coll.value !== undefined) {
					// either promote a DELETE element method to a collection method,
					// or integrate coll.name into a PUT element method data
					if (!data) data = {};
					if (data[coll.name] === undefined) data[coll.name] = coll.value;
				}
				invalidateAndSend(raja, {
					url: coll.url,
					method: method,
					mtime: now,
					data: ensureArray(data)
				});
			}
		});
		next();
	}
};

ExpressProxy.prototype.finished = function(url, code, mime, buf, resources) {
	this.raja.store.set(url, {
		code: code,
		data: buf,
		mime: mime,
		resources: resources && Object.keys(resources)
	}, this.raja.error);
};

function collectionInfo(routePath, url, params) {
	var find = /^:(.+)\?$/.exec(routePath.split('/').pop());
	if (find != null && params.hasOwnProperty(find[1])) {
		var name = find[1];
		var value = params[name];
		if (value !== undefined) {
			url = url.split('/');
			url.pop();
			url = url.join('/');
		}
		return {url: url, name: name, value: value};
	} else {
		return;
	}
}

function lastParam(routePath, url, param) {
	var keys = [];
	var regexp = pathRegexp(routePath, keys);
	var m = regexp.exec(URL.parse(url).pathname);
	if (!m) return;
	var val = m[m.length-1];
	var key = keys[keys.length-1];
	if (key.name != param) return;
	if (typeof val == 'string') {
		try {	val = decodeURIComponent(val); } catch (e) { val = undefined; }
	}
	return val;
}

function ensureArray(data) {
	if (!data || data.length == 0) {
		// empty
		data = [];
	} else if (Array.isArray(data)) {
		// all right, do nothing
	} else if (typeof data == "string") {
		// pure strings
		if (data[0] == '{') data = '[' + data + ']';
	} else if (typeof data.slice == "function") {
		// Buffers, bl-buffers
		if (data.slice(0, 1).toString() == '{') data = '[' + data.toString() + ']';
	} else if (typeof data == "object") {
		// pure objects
		data = [data];
	}
	return data;
}

function invalidateAndSend(raja, msg) {
	raja.store.invalidate(msg.url, function(err) {
		if (err) return raja.error(err);
		raja.send(msg);
	});
}

function getResource(referer, resources, remote, query, cb) {
	delete resources.__notcalled__;
	if (!cb && typeof query == "function") {
		cb = query;
		query = null;
	}
	if (query) {
		remote = urlParams(remote, query);
		remote = urlQuery(remote, query);
	}
	if (!/^https?:/.test(remote)) remote = absolute(URL.parse(referer), remote);
	this.remote.get(remote, function(err, data) {
		if (err >= 400 && err < 500) delete resources[remote];
		else if (!err) resources[remote] = true;
		cb(err, data);
	});
}

function absolute(loc, url) {
	if (/^https?/i.test(url)) return url;
	var path = loc.pathname;
	if (url.indexOf('..') == 0) {
		path = path.split('/');
		path.pop();
		url = path.join('/') + url.substring(2);
	} else if (url == '.') {
		return loc.href;
	} else if (url.indexOf('.') == 0) {
		url = path + url.substring(1);
	} else if (url.indexOf('/') != 0) {
		var base = path.split('/');
		base.pop();
		base = base.join('/');
		url = base + '/' + url;
	}
	url = loc.protocol + '//' + loc.host + url;
	return url;
}

function urlParams(url, params) {
	if (!params) return url;
	return url.replace(/\/:(\w+)/g, function(str, name) {
		var val = params[name];
		if (val != null) {
			delete params[name];
			return '/' + val;
		} else {
			return '/:' + name;
		}
	});
}

function urlQuery(url, query) {
	if (!query) return url;
	var comps = [];
	var str;
	for (var k in query) {
		str = encodeURIComponent(k);
		if (query[k] != null) str += '=' + encodeURIComponent(query[k]);
		comps.push(str);
	}
	if (comps.length) {
		if (url.indexOf('?') > 0) url += '&';
		else url += '?';
		url += comps.join('&');
	}
	return url;
}

<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom/server';
import serialize from 'serialize-javascript';
import Helmet from 'react-helmet';

/**
 * Wrapper component containing HTML metadata and boilerplate tags.
 * Used in server-side code only to wrap the string output of the
 * rendered route component.
 *
 * The only thing this component doesn't (and can't) include is the
 * HTML doctype declaration, which is added to the rendered output
 * by the server.js file.
 */
export default class Html extends Component {
  static propTypes = {
    assets: PropTypes.object,
    component: PropTypes.node,
    store: PropTypes.object
  };

  render() {
    const {assets, component, store} = this.props;
    const content = component ? ReactDOM.renderToString(component) : '';
    const head = Helmet.rewind();

    return (

          {head.base.toComponent()}
          {head.title.toComponent()}
          {head.meta.toComponent()}
          {head.link.toComponent()}
          {head.script.toComponent()}

          <link rel="shortcut icon" href="/favicon.ico" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          {/* styles (will be present only in production with webpack extract text plugin) */}
          {Object.keys(assets.styles).map((style, key) =>
            <link async href={assets.styles[style]} key={key} media="screen, projection"
                  rel="stylesheet" type="text/css" charSet="UTF-8"/>
          )}

          {/* (will be present only in development mode) */}
          {/* outputs a


<commit_before>/**
 * @file Nashorn host adapter
 * @since 0.2.4
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfHost*/ // Host type
/*global _gpfHostJava*/ // Common implementation for Java hosts
/*#endif*/

if (_GPF_HOST.NASHORN === _gpfHost) {

    _gpfHostJava();

}

/*#ifndef(UMD)*/

// Generates an empty function to reflect the null complexity of this module
function _gpfHostNashorn () {}
/*exported _gpfHostNashorn*/

/*#endif*/

<commit_msg>Also consider coverage (#240)<commit_after>/**
 * @file Nashorn host adapter
 * @since 0.2.4
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfHost*/ // Host type
/*global _gpfHostJava*/ // Common implementation for Java hosts
/*#endif*/

if (_GPF_HOST.NASHORN === _gpfHost) {

    _gpfHostJava();

}

/*#ifndef(UMD)*/

// Generates an empty function to reflect the null complexity of this module
(function _gpfHostNashorn () {}());

/*#endif*/
<|endoftext|>


<commit_before>var Utils     = require('./utils')
  , DataTypes = require('./data-types')

module.exports = (function() {
  var QueryInterface = function(sequelize) {
    this.sequelize = sequelize
    this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
  }
  Utils.addEventEmitter(QueryInterface)

  QueryInterface.prototype.createTable = function(tableName, attributes, options) {
    var attributeHashes = {}

    Utils._.each(attributes, function(dataTypeOrOptions, attributeName) {
      if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
        attributeHashes[attributeName] = { type: dataTypeOrOptions }
      else
        attributeHashes[attributeName] = dataTypeOrOptions
    })

    attributes = this.QueryGenerator.attributesToSQL(attributeHashes)

    var sql = this.QueryGenerator.createTableQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'createTable')
  }

  QueryInterface.prototype.dropTable = function(tableName) {
    var sql = this.QueryGenerator.dropTableQuery(tableName)
    return queryAndEmit.call(this, sql, 'dropTable')
  }

  QueryInterface.prototype.dropAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var chainer = new Utils.QueryChainer()

      self.showAllTables().success(function(tableNames) {
        tableNames.forEach(function(tableName) {
          chainer.add(self.sequelize.getQueryInterface().dropTable(tableName))
        })
        chainer
          .run()
          .success(function() {
            self.emit('dropAllTables', null)
            emitter.emit('success', null)
          })
          .error(function(err) {
            self.emit('dropAllTables', err)
            emitter.emit('failure', err)
          })
      }).error(function(err) {
        self.emit('dropAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.renameTable = function(before, after) {
    var sql = this.QueryGenerator.renameTableQuery(before, after)
    return queryAndEmit.call(this, sql, 'renameTable')
  }

  QueryInterface.prototype.showAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var showTablesSql = self.QueryGenerator.showTablesQuery()
      self.sequelize.query(showTablesSql, null, { raw: true }).success(function(tableNames) {
        self.emit('showAllTables', null)
        emitter.emit('success', Sequelize.Utils._.flatten(tableNames))
      }).error(function(err) {
        self.emit('showAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.describeTable = function(tableName) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('DESCRIBE `' + tableName + '`;', null, { raw: true }).success(function(data) {
        emitter.emit('success', data)
      }).error(function(err) {
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.addColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'addColumn')
  }

  QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
    var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
    return queryAndEmit.call(this, sql, 'removeColumn')
  }

  QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.changeColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'changeColumn')
  }

  QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.describeTable(tableName).success(function(data) {
        data = data.filter(function(h) { return h.Field == attrNameBefore })[0]

        var options =  {}

        options[attrNameAfter] = {
          type: data.Type,
          allowNull: data.Null == 'YES',
          defaultValue: data.Default
        }

        var sql = self.QueryGenerator.renameColumnQuery(tableName,
          attrNameBefore,
          self.QueryGenerator.attributesToSQL(options)
        )

        self.sequelize.query(sql).success(function() {
          self.emit('renameColumn', null)
          emitter.emit('success', null)
        }).error(function(err) {
          self.emit('renameColumn', err)
          emitter.emit('failure', err)
        })
      }).error(function(err) {
        self.emit('renameColumn', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
    var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'addIndex')
  }

  QueryInterface.prototype.showIndex = function(tableName, options) {
    var sql = this.QueryGenerator.showIndexQuery(tableName, options)
    return queryAndEmit.call(this, sql, 'showIndex')
  }

  QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) {
    var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes)
    return queryAndEmit.call(this, sql, "removeIndex")
  }

  QueryInterface.prototype.insert = function(model, tableName, values) {
    var sql = this.QueryGenerator.insertQuery(tableName, values)
    return queryAndEmit.call(this, [sql, model], 'insert', {
      success: function(obj) { obj.isNewRecord = false }
    })
  }

  QueryInterface.prototype.update = function(model, tableName, values, identifier) {
    var sql = this.QueryGenerator.updateQuery(tableName, values, identifier)
    return queryAndEmit.call(this, [sql, model], 'update')
  }

  QueryInterface.prototype.delete = function(model, tableName, identifier) {
    var sql = this.QueryGenerator.deleteQuery(tableName, identifier)
    return queryAndEmit.call(this, [sql, model], 'delete')
  }

  QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
    var sql = this.QueryGenerator.selectQuery(tableName, options)
    return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
  }

  QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
    var self = this

    if(attributeSelector == undefined)
      throw new Error('Please pass an attribute selector!')

    return new Utils.CustomEventEmitter(function(emitter) {
      var sql    = self.QueryGenerator.selectQuery(tableName, options)
        , _query = query.call(self, sql, null, { plain: true, raw: true })

      _query.success(function(data) {
        self.emit('rawSelect', null)
        emitter.emit('success', data[attributeSelector])
      }).error(function(err) {
        self.emit('rawSelect', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  // private

  var queryAndEmit = function(sqlOrQueryParams, methodName, options) {
    var self = this

    options = Utils._.extend({
      success: function(obj){},
      error: function(err){}
    }, options || {})

    return new Utils.CustomEventEmitter(function(emitter) {
      var query = null

      if(Array.isArray(sqlOrQueryParams))
        query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams)
      else
        query = self.sequelize.query(sqlOrQueryParams)

      // append the query for better testing
      emitter.query = query

      query.success(function(obj) {
        options.success && options.success(obj)
        self.emit(methodName, null)
        emitter.emit('success', obj)
      }).error(function(err) {
        options.error && options.error(err)
        self.emit(methodName, err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })

    // add this as callee via the second argument
    if(arguments.length == 1) args.push(this)

    return this.sequelize.query.apply(this.sequelize, args)
  }

  return QueryInterface
})()
<commit_msg>removed last usage of query method<commit_after>var Utils     = require('./utils')
  , DataTypes = require('./data-types')

module.exports = (function() {
  var QueryInterface = function(sequelize) {
    this.sequelize = sequelize
    this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
  }
  Utils.addEventEmitter(QueryInterface)

  QueryInterface.prototype.createTable = function(tableName, attributes, options) {
    var attributeHashes = {}

    Utils._.each(attributes, function(dataTypeOrOptions, attributeName) {
      if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
        attributeHashes[attributeName] = { type: dataTypeOrOptions }
      else
        attributeHashes[attributeName] = dataTypeOrOptions
    })

    attributes = this.QueryGenerator.attributesToSQL(attributeHashes)

    var sql = this.QueryGenerator.createTableQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'createTable')
  }

  QueryInterface.prototype.dropTable = function(tableName) {
    var sql = this.QueryGenerator.dropTableQuery(tableName)
    return queryAndEmit.call(this, sql, 'dropTable')
  }

  QueryInterface.prototype.dropAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var chainer = new Utils.QueryChainer()

      self.showAllTables().success(function(tableNames) {
        tableNames.forEach(function(tableName) {
          chainer.add(self.sequelize.getQueryInterface().dropTable(tableName))
        })
        chainer
          .run()
          .success(function() {
            self.emit('dropAllTables', null)
            emitter.emit('success', null)
          })
          .error(function(err) {
            self.emit('dropAllTables', err)
            emitter.emit('failure', err)
          })
      }).error(function(err) {
        self.emit('dropAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.renameTable = function(before, after) {
    var sql = this.QueryGenerator.renameTableQuery(before, after)
    return queryAndEmit.call(this, sql, 'renameTable')
  }

  QueryInterface.prototype.showAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var showTablesSql = self.QueryGenerator.showTablesQuery()
      self.sequelize.query(showTablesSql, null, { raw: true }).success(function(tableNames) {
        self.emit('showAllTables', null)
        emitter.emit('success', Sequelize.Utils._.flatten(tableNames))
      }).error(function(err) {
        self.emit('showAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.describeTable = function(tableName) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('DESCRIBE `' + tableName + '`;', null, { raw: true }).success(function(data) {
        emitter.emit('success', data)
      }).error(function(err) {
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.addColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'addColumn')
  }

  QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
    var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
    return queryAndEmit.call(this, sql, 'removeColumn')
  }

  QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = this.QueryGenerator.attributesToSQL(attributes)
      , sql     = this.QueryGenerator.changeColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'changeColumn')
  }

  QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.describeTable(tableName).success(function(data) {
        data = data.filter(function(h) { return h.Field == attrNameBefore })[0]

        var options =  {}

        options[attrNameAfter] = {
          type: data.Type,
          allowNull: data.Null == 'YES',
          defaultValue: data.Default
        }

        var sql = self.QueryGenerator.renameColumnQuery(tableName,
          attrNameBefore,
          self.QueryGenerator.attributesToSQL(options)
        )

        self.sequelize.query(sql).success(function() {
          self.emit('renameColumn', null)
          emitter.emit('success', null)
        }).error(function(err) {
          self.emit('renameColumn', err)
          emitter.emit('failure', err)
        })
      }).error(function(err) {
        self.emit('renameColumn', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
    var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'addIndex')
  }

  QueryInterface.prototype.showIndex = function(tableName, options) {
    var sql = this.QueryGenerator.showIndexQuery(tableName, options)
    return queryAndEmit.call(this, sql, 'showIndex')
  }

  QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) {
    var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes)
    return queryAndEmit.call(this, sql, "removeIndex")
  }

  QueryInterface.prototype.insert = function(model, tableName, values) {
    var sql = this.QueryGenerator.insertQuery(tableName, values)
    return queryAndEmit.call(this, [sql, model], 'insert', {
      success: function(obj) { obj.isNewRecord = false }
    })
  }

  QueryInterface.prototype.update = function(model, tableName, values, identifier) {
    var sql = this.QueryGenerator.updateQuery(tableName, values, identifier)
    return queryAndEmit.call(this, [sql, model], 'update')
  }

  QueryInterface.prototype.delete = function(model, tableName, identifier) {
    var sql = this.QueryGenerator.deleteQuery(tableName, identifier)
    return queryAndEmit.call(this, [sql, model], 'delete')
  }

  QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
    var sql = this.QueryGenerator.selectQuery(tableName, options)
    return queryAndEmit.call(this, [sql, factory, queryOptions], 'select')
  }

  QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
    var self = this

    if(attributeSelector == undefined)
      throw new Error('Please pass an attribute selector!')

    return new Utils.CustomEventEmitter(function(emitter) {
      var sql = self.QueryGenerator.selectQuery(tableName, options)

      self.sequelize
        .query(sql, null, { plain: true, raw: true })
        .success(function(data) {
          self.emit('rawSelect', null)
          emitter.emit('success', data[attributeSelector])
        })
        .error(function(err) {
          self.emit('rawSelect', err)
          emitter.emit('failure', err)
        })
    }).run()
  }

  // private

  var queryAndEmit = function(sqlOrQueryParams, methodName, options) {
    var self = this

    options = Utils._.extend({
      success: function(obj){},
      error: function(err){}
    }, options || {})

    return new Utils.CustomEventEmitter(function(emitter) {
      var query = null

      if(Array.isArray(sqlOrQueryParams))
        query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams)
      else
        query = self.sequelize.query(sqlOrQueryParams)

      // append the query for better testing
      emitter.query = query

      query.success(function(obj) {
        options.success && options.success(obj)
        self.emit(methodName, null)
        emitter.emit('success', obj)
      }).error(function(err) {
        options.error && options.error(err)
        self.emit(methodName, err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })

    // add this as callee via the second argument
    if(arguments.length == 1) args.push(this)

    return this.sequelize.query.apply(this.sequelize, args)
  }

  return QueryInterface
})()
<|endoftext|>