<commit_before>//TODO: think of how to handle params from router

// settings
// postHash
// routes start with / you can define a 404

var vm = require( 'bw-vm' ),
	viewmediator = require( 'bw-viewmediator' ),
	routes = require( 'routes' );

function bigwheel( settings ) {

	if( !( this instanceof bigwheel ) )
		return new bigwheel( settings );

	var s = this.s = settings || {};

	s.postHash = s.postHash || '!';

	this.onURL = this.onURL.bind( this );

	this.router = routes();
	this.vm = vm( this.s );
};

bigwheel.prototype = {

	init: function() {

		var s = this.s,
			noop = function() {};

		// figure out a start section
		if( s[ '/' ] === undefined ) {

			// find the first path which would be a section
			for( var i in s ) {

				if( i[ 0 ] == '/' ) {

					s.start = i;

					break;
				}
			}
		} else {

			s.start = '/';
		}

		// now setup routes
		for( var i in s ) {

			if( i[ 0 ] == '/' ) {

				this.router.addRoute( i, noop );
			}
		}

		window.addEventListener( 'hashchange', this.onURL );

		// force a hash change to start things up
		this.onURL();

		return this;
	},

	add: function( route, section ) {

		var s = this.s;

		s[ route ] = section;

		return this;
	},

	go: function( to ) {

		if( to[ 0 ] != '/' )
			to = '/' + to;

		window.location.hash = this.s.postHash + to;
	},

	show: function( content ) {

		//check if content is an array or function or object

		if( Array.isArray( content ) ) {

			var contents = [];

			for( var i = 0, len = content.length; i < len; i++ ) {

				if( typeof content[ i ] == 'object' )
					contents[ i ] = content[ i ];
				else if( typeof content[ i ] == 'function' )
					contents[ i ] = new content[ i ];
			}

			this.doShow( viewmediator.apply( undefined, contents ) );
		} else if( typeof content == 'object' ) {

			this.doShow( content );
		} else if( typeof content == 'function' ) {

			this.doShow( new content );
		}
	},

	doShow: function( content ) {

		this.vm.show( content );
	},

	doRoute: function( data ) {

		var s = this.s,
			section;

		if( data ) {

			section = s[ data.route ];
		}

		if( section ) {

			this.show( section );
		} else if( s[ '404' ] ) {

			this.show( s[ '404' ] );
		}
	},

	onURL: function() {

		var cRoute = '/';

		if( window.location.hash != '' ) {

			cRoute = window.location.hash.substr( 1 + this.s.postHash.length );
		}

		console.log( cRoute );

		this.doRoute( this.router.match( cRoute ) );
	}
};

module.exports = bigwheel;<commit_msg>Implemented resizing<commit_after>//TODO: think of how to handle params from router

// settings
// postHash
// routes start with / you can define a 404

var vm = require( 'bw-vm' ),
	viewmediator = require( 'bw-viewmediator' ),
	routes = require( 'routes' );

function addEventListener( to, event, listener ) {

	if( to.attachEvent ) {

	    to.attachEvent( event, listener );
	} else if( to.addEventListener ) {

	    to.addEventListener( event, listener, true);
	}
	else {

	    to[ 'on' + event ] = listener;
	}
}

function bigwheel( settings ) {

	if( !( this instanceof bigwheel ) )
		return new bigwheel( settings );

	var s = this.s = settings || {};

	s.postHash = s.postHash || '!';

	this.router = routes();
	this.vm = vm( this.s );

	this.onResize();
};

bigwheel.prototype = {

	init: function() {

		var s = this.s,
			noop = function() {};

		// figure out a start section
		if( s[ '/' ] === undefined ) {

			// find the first path which would be a section
			for( var i in s ) {

				if( i[ 0 ] == '/' ) {

					s.start = i;

					break;
				}
			}
		} else {

			s.start = '/';
		}

		// now setup routes
		for( var i in s ) {

			if( i[ 0 ] == '/' ) {

				this.router.addRoute( i, noop );
			}
		}

		addEventListener( window, 'hashchange', this.onURL.bind( this ) );
		addEventListener( window, 'resize', this.onResize.bind( this ) );

		// force a hash change to start things up
		this.onURL();

		return this;
	},

	add: function( route, section ) {

		var s = this.s;

		s[ route ] = section;

		return this;
	},

	go: function( to ) {

		if( to[ 0 ] != '/' )
			to = '/' + to;

		window.location.hash = this.s.postHash + to;
	},

	show: function( content ) {

		//check if content is an array or function or object

		if( Array.isArray( content ) ) {

			var contents = [];

			for( var i = 0, len = content.length; i < len; i++ ) {

				if( typeof content[ i ] == 'object' )
					contents[ i ] = content[ i ];
				else if( typeof content[ i ] == 'function' )
					contents[ i ] = new content[ i ];
			}

			this.doShow( viewmediator.apply( undefined, contents ) );
		} else if( typeof content == 'object' ) {

			this.doShow( content );
		} else if( typeof content == 'function' ) {

			this.doShow( new content );
		}
	},

	doShow: function( content ) {

		this.vm.show( content );
	},

	doRoute: function( data ) {

		var s = this.s,
			section;

		if( data ) {

			section = s[ data.route ];
		}

		if( section ) {

			this.show( section );
		} else if( s[ '404' ] ) {

			this.show( s[ '404' ] );
		}
	},

	onResize: function() {

		this.vm.resize( window.innerWidth, window.innerHeight );
	},

	onURL: function() {

		var cRoute = '/';

		if( window.location.hash != '' ) {

			cRoute = window.location.hash.substr( 1 + this.s.postHash.length );
		}

		console.log( cRoute );

		this.doRoute( this.router.match( cRoute ) );
	}
};

module.exports = bigwheel;<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { ActivityIndicator, Image, StyleSheet, View } from 'react-native';

const styles = StyleSheet.create({
  centered: {
    ...StyleSheet.absoluteFillObject,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const DefaultIndicator = ActivityIndicator;

export const createImageProgress = ImageComponent =>
  class ImageProgress extends Component {
    static propTypes = {
      children: PropTypes.node,
      errorContainerStyle: PropTypes.any,
      indicator: PropTypes.func,
      indicatorContainerStyle: PropTypes.any,
      indicatorProps: PropTypes.object,
      renderIndicator: PropTypes.func,
      renderError: PropTypes.func,
      source: PropTypes.any,
      style: PropTypes.any,
      imageStyle: PropTypes.object,
      threshold: PropTypes.number.isRequired,
    };

    static defaultProps = {
      indicatorContainerStyle: styles.centered,
      errorContainerStyle: styles.centered,
      threshold: 50,
    };

    static prefetch = Image.prefetch;
    static getSize = Image.getSize;

    constructor(props) {
      super(props);

      this.state = {
        error: null,
        loading: false,
        progress: 0,
        thresholdReached: !props.threshold,
      };
    }

    componentDidMount() {
      if (this.props.threshold) {
        this.thresholdTimer = setTimeout(() => {
          this.setState({ thresholdReached: true });
          this.thresholdTimer = null;
        }, this.props.threshold);
      }
    }

    componentWillReceiveProps(props) {
      if (
        !this.props.source ||
        !props.source ||
        this.props.source.uri !== props.source.uri
      ) {
        this.setState({
          error: null,
          loading: false,
          progress: 0,
        });
      }
    }

    componentWillUnmount() {
      if (this.thresholdTimer) {
        clearTimeout(this.thresholdTimer);
      }
    }

    setNativeProps(nativeProps) {
      if (this.ref) {
        this.ref.setNativeProps(nativeProps);
      }
    }

    measure(cb) {
      if (this.ref) {
        this.ref.measure(cb);
      }
    }

    ref = null;
    handleRef = ref => {
      this.ref = ref;
    };

    bubbleEvent(propertyName, event) {
      if (typeof this.props[propertyName] === 'function') {
        this.props[propertyName](event);
      }
    }

    handleLoadStart = () => {
      if (!this.state.loading && this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: true,
          progress: 0,
        });
      }
      this.bubbleEvent('onLoadStart');
    };

    handleProgress = event => {
      const progress = event.nativeEvent.loaded / event.nativeEvent.total;
      // RN is a bit buggy with these events, sometimes a loaded event and then a few
      // 100% progress – sometimes in an infinite loop. So we just assume 100% progress
      // actually means the image is no longer loading
      if (progress !== this.state.progress && this.state.progress !== 1) {
        this.setState({
          loading: progress < 1,
          progress,
        });
      }
      this.bubbleEvent('onProgress', event);
    };

    handleError = event => {
      this.setState({
        loading: false,
        error: event.nativeEvent,
      });
      this.bubbleEvent('onError', event);
    };

    handleLoad = event => {
      if (this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: false,
          progress: 1,
        });
      }
      this.bubbleEvent('onLoad', event);
    };

    onLoadEnd = event => {
      this.setState({
        error: null,
        loading: false,
        progress: 1,
      });
      this.bubbleEvent('onLoadEnd', event);
    }

    render() {
      const {
        children,
        errorContainerStyle,
        indicator,
        indicatorContainerStyle,
        indicatorProps,
        renderError,
        renderIndicator,
        source,
        style,
        threshold,
        imageStyle,
        ...props
      } = this.props;

      if (!source || !source.uri) {
        // This is not a networked asset so fallback to regular image
        return (
          <View style={style} ref={this.handleRef}>
            <ImageComponent
              {...props}
              source={source}
              style={[StyleSheet.absoluteFill, imageStyle]}
            />
            {children}
          </View>
        );
      }
      const { progress, thresholdReached, loading, error } = this.state;

      let indicatorElement;

      if (error) {
        if (renderError) {
          indicatorElement = (
            <View style={errorContainerStyle}>{renderError(error)}</View>
          );
        }
      } else if ((loading || progress < 1) && thresholdReached) {
        if (renderIndicator) {
          indicatorElement = renderIndicator(progress, !loading || !progress);
        } else {
          const IndicatorComponent = typeof indicator === 'function'
            ? indicator
            : DefaultIndicator;
          indicatorElement = (
            <IndicatorComponent
              progress={progress}
              indeterminate={!loading || !progress}
              {...indicatorProps}
            />
          );
        }
        indicatorElement = (
          <View style={indicatorContainerStyle}>{indicatorElement}</View>
        );
      }

      return (
        <View style={style} ref={this.handleRef}>
          <ImageComponent
            {...props}
            key={source && source.uri}
            onLoadStart={this.handleLoadStart}
            onProgress={this.handleProgress}
            onError={this.handleError}
            onLoad={this.handleLoad}
            onLoadEnd={this.onLoadEnd}
            source={source}
            style={[StyleSheet.absoluteFill, imageStyle]}
          />
          {indicatorElement}
          {children}
        </View>
      );
    }
  };

export default createImageProgress(Image);
<commit_msg>Fixed clearing error by onLoadEnd (#76)<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { ActivityIndicator, Image, StyleSheet, View } from 'react-native';

const styles = StyleSheet.create({
  centered: {
    ...StyleSheet.absoluteFillObject,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const DefaultIndicator = ActivityIndicator;

export const createImageProgress = ImageComponent =>
  class ImageProgress extends Component {
    static propTypes = {
      children: PropTypes.node,
      errorContainerStyle: PropTypes.any,
      indicator: PropTypes.func,
      indicatorContainerStyle: PropTypes.any,
      indicatorProps: PropTypes.object,
      renderIndicator: PropTypes.func,
      renderError: PropTypes.func,
      source: PropTypes.any,
      style: PropTypes.any,
      imageStyle: PropTypes.object,
      threshold: PropTypes.number.isRequired,
    };

    static defaultProps = {
      indicatorContainerStyle: styles.centered,
      errorContainerStyle: styles.centered,
      threshold: 50,
    };

    static prefetch = Image.prefetch;
    static getSize = Image.getSize;

    constructor(props) {
      super(props);

      this.state = {
        error: null,
        loading: false,
        progress: 0,
        thresholdReached: !props.threshold,
      };
    }

    componentDidMount() {
      if (this.props.threshold) {
        this.thresholdTimer = setTimeout(() => {
          this.setState({ thresholdReached: true });
          this.thresholdTimer = null;
        }, this.props.threshold);
      }
    }

    componentWillReceiveProps(props) {
      if (
        !this.props.source ||
        !props.source ||
        this.props.source.uri !== props.source.uri
      ) {
        this.setState({
          error: null,
          loading: false,
          progress: 0,
        });
      }
    }

    componentWillUnmount() {
      if (this.thresholdTimer) {
        clearTimeout(this.thresholdTimer);
      }
    }

    setNativeProps(nativeProps) {
      if (this.ref) {
        this.ref.setNativeProps(nativeProps);
      }
    }

    measure(cb) {
      if (this.ref) {
        this.ref.measure(cb);
      }
    }

    ref = null;
    handleRef = ref => {
      this.ref = ref;
    };

    bubbleEvent(propertyName, event) {
      if (typeof this.props[propertyName] === 'function') {
        this.props[propertyName](event);
      }
    }

    handleLoadStart = () => {
      if (!this.state.loading && this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: true,
          progress: 0,
        });
      }
      this.bubbleEvent('onLoadStart');
    };

    handleProgress = event => {
      const progress = event.nativeEvent.loaded / event.nativeEvent.total;
      // RN is a bit buggy with these events, sometimes a loaded event and then a few
      // 100% progress – sometimes in an infinite loop. So we just assume 100% progress
      // actually means the image is no longer loading
      if (progress !== this.state.progress && this.state.progress !== 1) {
        this.setState({
          loading: progress < 1,
          progress,
        });
      }
      this.bubbleEvent('onProgress', event);
    };

    handleError = event => {
      this.setState({
        loading: false,
        error: event.nativeEvent,
      });
      this.bubbleEvent('onError', event);
    };

    handleLoad = event => {
      if (this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: false,
          progress: 1,
        });
      }
      this.bubbleEvent('onLoad', event);
    };

    onLoadEnd = event => {
      this.setState({
        loading: false,
        progress: 1,
      });
      this.bubbleEvent('onLoadEnd', event);
    }

    render() {
      const {
        children,
        errorContainerStyle,
        indicator,
        indicatorContainerStyle,
        indicatorProps,
        renderError,
        renderIndicator,
        source,
        style,
        threshold,
        imageStyle,
        ...props
      } = this.props;

      if (!source || !source.uri) {
        // This is not a networked asset so fallback to regular image
        return (
          <View style={style} ref={this.handleRef}>
            <ImageComponent
              {...props}
              source={source}
              style={[StyleSheet.absoluteFill, imageStyle]}
            />
            {children}
          </View>
        );
      }
      const { progress, thresholdReached, loading, error } = this.state;

      let indicatorElement;

      if (error) {
        if (renderError) {
          indicatorElement = (
            <View style={errorContainerStyle}>{renderError(error)}</View>
          );
        }
      } else if ((loading || progress < 1) && thresholdReached) {
        if (renderIndicator) {
          indicatorElement = renderIndicator(progress, !loading || !progress);
        } else {
          const IndicatorComponent = typeof indicator === 'function'
            ? indicator
            : DefaultIndicator;
          indicatorElement = (
            <IndicatorComponent
              progress={progress}
              indeterminate={!loading || !progress}
              {...indicatorProps}
            />
          );
        }
        indicatorElement = (
          <View style={indicatorContainerStyle}>{indicatorElement}</View>
        );
      }

      return (
        <View style={style} ref={this.handleRef}>
          <ImageComponent
            {...props}
            key={source && source.uri}
            onLoadStart={this.handleLoadStart}
            onProgress={this.handleProgress}
            onError={this.handleError}
            onLoad={this.handleLoad}
            onLoadEnd={this.onLoadEnd}
            source={source}
            style={[StyleSheet.absoluteFill, imageStyle]}
          />
          {indicatorElement}
          {children}
        </View>
      );
    }
  };

export default createImageProgress(Image);
<|endoftext|>


<commit_before>'use strict'

const gutil = require('gulp-util')
const through = require('through2')
const titleCase = require('title-case')
const fs = require('fs-extra')
const _exec = require('child_process').exec
require('shelljs/global')

const P = 'gulp-debian'

function deb (files, pkg, cb) {
  let ctrl = []
  for (let key in pkg) {
    ctrl.push(`${titleCase(key)}: ${pkg[key]}`)
  }
  ctrl.push(' ')
  return cb(null, ctrl)
}

function changelog (pkg) {
  let log = []
  for (let i = 0; i < pkg.changelog.length; i++) {
    let header = `${pkg.package} (${pkg.changelog[i].version}) `
    header += `${pkg.changelog[i].distribution}; urgency=${pkg.changelog[i].urgency}`
    log.push(header + '\n')
    for (let x = 0; x < pkg.changelog[i].changes.length; x++) {
      log.push(`\t * ${pkg.changelog[i].changes[x]}`)
    }
    const ts = Date.parse(pkg.changelog[i].date)
    log.push(`\n-- ${pkg.maintainer} ${new Date(ts)}\n`)
  }
  return log
}

function installScript (fn, script, out, cb) {
  if (script !== undefined && script.length > 0) {
    script.push('')
    const o = `${out}/DEBIAN/${fn}`
    fs.outputFile(o, script.join('\n'), function (err) {
      if (err) {
        cb(new gutil.PluginError(P, err))
        return
      }
      chmod(644, o)
    })
  }
}

module.exports = function (pkg) {
  let files = []
  return through.obj(function (file, enc, cb) {
    if (file.isStream()) {
      cb(new gutil.PluginError(P, 'Streaming not supported.'))
      return
    }
    files.push(file)
    cb(null)
  }, function (cb) {
    deb(files, pkg, function (err, ctrl) {
      if (pkg._verbose === undefined) {
        pkg._verbose = true
      }
      if (pkg._target === undefined || pkg._out === undefined) {
        cb(new gutil.PluginError(P, '_target and/or _out undefined.'))
        return
      }
      if (err) {
        cb(new gutil.PluginError(P, err, {filename: files[0].path}))
        return
      }
      let out = `${pkg._out}/${pkg.package}_${pkg.version}_${pkg.architecture}`
      installScript('preinst', pkg.preinst, out, cb)
      installScript('postinst', pkg.postinst, out, cb)
      ctrl = ctrl.filter(function (line) {
        if (!/Out|Target|Verbose|Changelog|Preinst|Postinst/.test(line)) {
          return line
        }
      })
      const logf = changelog(pkg)
      if (logf.length > 0) {
        fs.mkdirpSync(`${out}/usr/share/doc/${pkg.package}`)
        fs.outputFile(`${out}/usr/share/doc/${pkg.package}/changelog.Debian`, logf.join('\n'),
        function (err) {
          if (err) {
            cb(new gutil.PluginError(P, err))
            return
          }
        })
      }
      const ctrlf = ctrl.join('\n')
      fs.outputFile(`${out}/DEBIAN/control`, ctrlf.substr(0, ctrlf.length - 1),
      function (err) {
        if (err) {
          cb(new gutil.PluginError(P, err))
          return
        }
        files.map(function (f) {
          let t = f.path.split('/')
          t = t[t.length - 1]
          fs.copySync(f.path, `${out}/${pkg._target}/${t}`)
        })
        _exec(`dpkg-deb --build ${pkg._out}/${pkg.package}_${pkg.version}_${pkg.architecture}`,
        function (err, stdout, stderr) {
          if (pkg._verbose && stdout.length > 1) {
            gutil.log(stdout.trim() + '\n')
          }
          if (stderr) {
            gutil.log(gutil.colors.red(stderr.trim()))
            cb(err)
          }
        })
      })
    })
  })
}
<commit_msg>chmod(755, o)<commit_after>'use strict'

const gutil = require('gulp-util')
const through = require('through2')
const titleCase = require('title-case')
const fs = require('fs-extra')
const _exec = require('child_process').exec
require('shelljs/global')

const P = 'gulp-debian'

function deb (files, pkg, cb) {
  let ctrl = []
  for (let key in pkg) {
    ctrl.push(`${titleCase(key)}: ${pkg[key]}`)
  }
  ctrl.push(' ')
  return cb(null, ctrl)
}

function changelog (pkg) {
  let log = []
  for (let i = 0; i < pkg.changelog.length; i++) {
    let header = `${pkg.package} (${pkg.changelog[i].version}) `
    header += `${pkg.changelog[i].distribution}; urgency=${pkg.changelog[i].urgency}`
    log.push(header + '\n')
    for (let x = 0; x < pkg.changelog[i].changes.length; x++) {
      log.push(`\t * ${pkg.changelog[i].changes[x]}`)
    }
    const ts = Date.parse(pkg.changelog[i].date)
    log.push(`\n-- ${pkg.maintainer} ${new Date(ts)}\n`)
  }
  return log
}

function installScript (fn, script, out, cb) {
  if (script !== undefined && script.length > 0) {
    script.push('')
    const o = `${out}/DEBIAN/${fn}`
    fs.outputFile(o, script.join('\n'), function (err) {
      if (err) {
        cb(new gutil.PluginError(P, err))
        return
      }
      chmod(755, o)
    })
  }
}

module.exports = function (pkg) {
  let files = []
  return through.obj(function (file, enc, cb) {
    if (file.isStream()) {
      cb(new gutil.PluginError(P, 'Streaming not supported.'))
      return
    }
    files.push(file)
    cb(null)
  }, function (cb) {
    deb(files, pkg, function (err, ctrl) {
      if (pkg._verbose === undefined) {
        pkg._verbose = true
      }
      if (pkg._target === undefined || pkg._out === undefined) {
        cb(new gutil.PluginError(P, '_target and/or _out undefined.'))
        return
      }
      if (err) {
        cb(new gutil.PluginError(P, err, {filename: files[0].path}))
        return
      }
      let out = `${pkg._out}/${pkg.package}_${pkg.version}_${pkg.architecture}`
      installScript('preinst', pkg.preinst, out, cb)
      installScript('postinst', pkg.postinst, out, cb)
      ctrl = ctrl.filter(function (line) {
        if (!/Out|Target|Verbose|Changelog|Preinst|Postinst/.test(line)) {
          return line
        }
      })
      const logf = changelog(pkg)
      if (logf.length > 0) {
        fs.mkdirpSync(`${out}/usr/share/doc/${pkg.package}`)
        fs.outputFile(`${out}/usr/share/doc/${pkg.package}/changelog.Debian`, logf.join('\n'),
        function (err) {
          if (err) {
            cb(new gutil.PluginError(P, err))
            return
          }
        })
      }
      const ctrlf = ctrl.join('\n')
      fs.outputFile(`${out}/DEBIAN/control`, ctrlf.substr(0, ctrlf.length - 1),
      function (err) {
        if (err) {
          cb(new gutil.PluginError(P, err))
          return
        }
        files.map(function (f) {
          let t = f.path.split('/')
          t = t[t.length - 1]
          fs.copySync(f.path, `${out}/${pkg._target}/${t}`)
        })
        _exec(`dpkg-deb --build ${pkg._out}/${pkg.package}_${pkg.version}_${pkg.architecture}`,
        function (err, stdout, stderr) {
          if (pkg._verbose && stdout.length > 1) {
            gutil.log(stdout.trim() + '\n')
          }
          if (stderr) {
            gutil.log(gutil.colors.red(stderr.trim()))
            cb(err)
          }
        })
      })
    })
  })
}
<|endoftext|>


<commit_before>var multilevel = require('multilevel'),
    HashRing = require('hashring'),
    bytewise = require('bytewise/hex'),
    encodeKey = bytewise.encode.bind(bytewise),
    net = require('net'),
    after = require('after'),
    merge = require('mergesort-stream'),
    through = require('through'),
    clone = require('clone'),
    setImmediate = global.setImmediate || process.nextTick;

module.exports = LevelCluster;

function LevelCluster(_servers, options) {
  options = options || {};
  this._servers = _servers;
  this.ring = _servers.reduce(function (acc, item) {
    acc.add(item);
    return acc;
  }, new HashRing());
  this.servers = {};
}

LevelCluster.prototype.put = function (key, value, cb) {
  var db = this.getServerByKey(key);
  return db.put(key, value, cb);
};

LevelCluster.prototype.get = function (key, cb) {
  var db = this.getServerByKey(key);
  return db.get(key, cb);
};

LevelCluster.prototype.del = function (key, cb) {
  var db = this.getServerByKey(key);
  return db.del(key, cb);
};

LevelCluster.prototype.batch = function (batch, cb) {
  var self = this;
  var batches = batch.reduce(function (acc, item) {
    var serverName = self.getServerNameByKey(item.key);
    acc[serverName] = acc[serverName] || [];
    acc[serverName].push(item);
    return acc;
  }, {});
  var keys = Object.keys(batches);
  var next = after(keys.length, cb);
  keys.forEach(function (serverName) {
    var server = self.getServerByName(serverName);
    var batch = batches[serverName];
    server.batch(batch, next);
  });
};

LevelCluster.prototype.createReadStream = function (options) {
  options = options || {};
  var _options = clone(options);
  // we need to the keys in order to sort the values in the right order
  options.keys = true;
  options.values = true;

  this.connectAllServers();
  var serverKeys = Object.keys(this.servers);
  var self = this;
  var streams = [];
  serverKeys.forEach(function (serverKey) {
    var server = self.servers[serverKey];
    streams.push(server.createReadStream(options));
  });
  var aggregator = merge(compare, streams);
  streams.forEach(function (stream) {
    stream.on('error', function (err) {
      // for some reason we get this error
      if (err.toString() !== 'Error: unexpected disconnection')
        aggregator.emit('error', err);
    });
  });
  var t = through(function (data) {
    if (_options && _options.keys === false) {
      this.queue(data.value);
    } else if (_options && _options.keys === true && _options.values === false) {
      this.queue(data.key);
    } else {
      this.queue(data);
    }
  });
  aggregator.pipe(t);
  return t;
};

LevelCluster.prototype.createKeyStream = function (options) {
  this.connectAllServers();
  var serverKeys = Object.keys(this.servers);
  var self = this;
  var streams = [];
  serverKeys.forEach(function (serverKey) {
    var server = self.servers[serverKey];
    streams.push(server.createKeyStream(options));
  });
  var aggregator = merge(compareKeys, streams);
  streams.forEach(function (stream) {
    stream.on('error', function (err) {
      // for some reason we get this error
      if (err.toString() !== 'Error: unexpected disconnection')
        aggregator.emit('error', err);
    });
  });
  return aggregator;
};

LevelCluster.prototype.createValueStream = function (options) {
  options = options || {};
  // we need to the keys in order to sort the values in the right order
  options.keys = false;
  options.values = true;
  return this.createReadStream(options);
};

LevelCluster.prototype.createWriteStream = function (options) {
  options = options || {};
  options.type = options.type || 'put';

  var t = through(write, end);
  var inflight = 0;
  var self = this;
  var ended = false;

  function write(data) {
    inflight++;
    var _type = data.type || options.type;
    if (_type !== 'del' && _type !== 'put') _type = 'put';
    if (_type === 'del') {
      self.del(data.key, cb.bind(this, data));
    } else {
      self.put(data.key, data.value, cb.bind(this, data));
    }
  }

  function cb(data, err) {
    --inflight;
    if (err) {
      return this.emit('error', err);
    }
    this.queue(data);
    if (inflight === 0 && ended) {
      this.queue(null);
    }
  }

  function end() {
    ended = true;
    if (inflight === 0 && ended) {
      this.queue(null);
    }
  }

  return t;
};

LevelCluster.prototype.close = function (cb) {
  var serverKeys = Object.keys(this.servers);
  var next = after(serverKeys.length, cb);
  var self = this;
  serverKeys.forEach(function (key) {
    var db = self.servers[key];
    db.close(next);
  });
};

LevelCluster.prototype.connectAllServers = function () {
  var self = this;
  self._servers.forEach(function (serverName) {
    var server = self.getServerByName(serverName);
  });
};

LevelCluster.prototype.getServerNameByKey = function (key) {
  return this.ring.get(encodeKey(key));
};

LevelCluster.prototype.getServerByKey = function (key) {
  var server = this.getServerNameByKey(key);
  return this.getServerByName(server);
};

LevelCluster.prototype.getServerByName = function (server) {
  if (typeof this.servers[server] === 'undefined') {
    this.servers[server] = getServer(server);
  }
  return this.servers[server];
};

function getServer(server) {
  var parts = server.split(':');
  var port = parts[1];
  var db = multilevel.client();
  var con = net.connect(port);
  con.pipe(db.createRpcStream()).pipe(con);
  db.serverName = server;
  return db;
}

function compare(value1, value2) {
  var key1 = encodeKey(value1.key),
      key2 = encodeKey(value2.key);
  if (key1 > key2) return 1;
  else if (key1 < key2) return -1;
  return 0;
}

function compareKeys(value1, value2) {
  var key1 = encodeKey(value1),
      key2 = encodeKey(value2);
  if (key1 > key2) return 1;
  else if (key1 < key2) return -1;
  return 0;
}
<commit_msg>use hostname<commit_after>var multilevel = require('multilevel'),
    HashRing = require('hashring'),
    bytewise = require('bytewise/hex'),
    encodeKey = bytewise.encode.bind(bytewise),
    net = require('net'),
    after = require('after'),
    merge = require('mergesort-stream'),
    through = require('through'),
    clone = require('clone'),
    setImmediate = global.setImmediate || process.nextTick;

module.exports = LevelCluster;

function LevelCluster(_servers, options) {
  options = options || {};
  this._servers = _servers;
  this.ring = _servers.reduce(function (acc, item) {
    acc.add(item);
    return acc;
  }, new HashRing());
  this.servers = {};
}

LevelCluster.prototype.put = function (key, value, cb) {
  var db = this.getServerByKey(key);
  return db.put(key, value, cb);
};

LevelCluster.prototype.get = function (key, cb) {
  var db = this.getServerByKey(key);
  return db.get(key, cb);
};

LevelCluster.prototype.del = function (key, cb) {
  var db = this.getServerByKey(key);
  return db.del(key, cb);
};

LevelCluster.prototype.batch = function (batch, cb) {
  var self = this;
  var batches = batch.reduce(function (acc, item) {
    var serverName = self.getServerNameByKey(item.key);
    acc[serverName] = acc[serverName] || [];
    acc[serverName].push(item);
    return acc;
  }, {});
  var keys = Object.keys(batches);
  var next = after(keys.length, cb);
  keys.forEach(function (serverName) {
    var server = self.getServerByName(serverName);
    var batch = batches[serverName];
    server.batch(batch, next);
  });
};

LevelCluster.prototype.createReadStream = function (options) {
  options = options || {};
  var _options = clone(options);
  // we need to the keys in order to sort the values in the right order
  options.keys = true;
  options.values = true;

  this.connectAllServers();
  var serverKeys = Object.keys(this.servers);
  var self = this;
  var streams = [];
  serverKeys.forEach(function (serverKey) {
    var server = self.servers[serverKey];
    streams.push(server.createReadStream(options));
  });
  var aggregator = merge(compare, streams);
  streams.forEach(function (stream) {
    stream.on('error', function (err) {
      // for some reason we get this error
      if (err.toString() !== 'Error: unexpected disconnection')
        aggregator.emit('error', err);
    });
  });
  var t = through(function (data) {
    if (_options && _options.keys === false) {
      this.queue(data.value);
    } else if (_options && _options.keys === true && _options.values === false) {
      this.queue(data.key);
    } else {
      this.queue(data);
    }
  });
  aggregator.pipe(t);
  return t;
};

LevelCluster.prototype.createKeyStream = function (options) {
  this.connectAllServers();
  var serverKeys = Object.keys(this.servers);
  var self = this;
  var streams = [];
  serverKeys.forEach(function (serverKey) {
    var server = self.servers[serverKey];
    streams.push(server.createKeyStream(options));
  });
  var aggregator = merge(compareKeys, streams);
  streams.forEach(function (stream) {
    stream.on('error', function (err) {
      // for some reason we get this error
      if (err.toString() !== 'Error: unexpected disconnection')
        aggregator.emit('error', err);
    });
  });
  return aggregator;
};

LevelCluster.prototype.createValueStream = function (options) {
  options = options || {};
  // we need to the keys in order to sort the values in the right order
  options.keys = false;
  options.values = true;
  return this.createReadStream(options);
};

LevelCluster.prototype.createWriteStream = function (options) {
  options = options || {};
  options.type = options.type || 'put';

  var t = through(write, end);
  var inflight = 0;
  var self = this;
  var ended = false;

  function write(data) {
    inflight++;
    var _type = data.type || options.type;
    if (_type !== 'del' && _type !== 'put') _type = 'put';
    if (_type === 'del') {
      self.del(data.key, cb.bind(this, data));
    } else {
      self.put(data.key, data.value, cb.bind(this, data));
    }
  }

  function cb(data, err) {
    --inflight;
    if (err) {
      return this.emit('error', err);
    }
    this.queue(data);
    if (inflight === 0 && ended) {
      this.queue(null);
    }
  }

  function end() {
    ended = true;
    if (inflight === 0 && ended) {
      this.queue(null);
    }
  }

  return t;
};

LevelCluster.prototype.close = function (cb) {
  var serverKeys = Object.keys(this.servers);
  var next = after(serverKeys.length, cb);
  var self = this;
  serverKeys.forEach(function (key) {
    var db = self.servers[key];
    db.close(next);
  });
};

LevelCluster.prototype.connectAllServers = function () {
  var self = this;
  self._servers.forEach(function (serverName) {
    var server = self.getServerByName(serverName);
  });
};

LevelCluster.prototype.getServerNameByKey = function (key) {
  return this.ring.get(encodeKey(key));
};

LevelCluster.prototype.getServerByKey = function (key) {
  var server = this.getServerNameByKey(key);
  return this.getServerByName(server);
};

LevelCluster.prototype.getServerByName = function (server) {
  if (typeof this.servers[server] === 'undefined') {
    this.servers[server] = getServer(server);
  }
  return this.servers[server];
};

function getServer(server) {
  var parts = server.split(':');
  var host = parts[0];
  var port = parts[1];
  var db = multilevel.client();
  var con = net.connect({ host: host, port: port });
  con.pipe(db.createRpcStream()).pipe(con);
  db.serverName = server;
  return db;
}

function compare(value1, value2) {
  var key1 = encodeKey(value1.key),
      key2 = encodeKey(value2.key);
  if (key1 > key2) return 1;
  else if (key1 < key2) return -1;
  return 0;
}

function compareKeys(value1, value2) {
  var key1 = encodeKey(value1),
      key2 = encodeKey(value2);
  if (key1 > key2) return 1;
  else if (key1 < key2) return -1;
  return 0;
}
<|endoftext|>


<commit_before>var create = require('./create')
var path = require('path')
var Inject = require('./inject')
var Set = require('./set')
var Level = require('level')

exports.manifest = {
  get: 'source',
  add: 'sink',
  ls: 'source',
  has: 'async',
  size: 'async',
  meta: 'async',
  want: 'async',
  push: 'async',
  changes: 'source',
  createWants: 'source'
}

exports.name = 'blobs'

exports.version = require('./package.json').version

exports.permissions = {
    anonymous: {allow: ['has', 'get', 'changes', 'createWants']},
}

exports.init = function (sbot, config) {
  var blobs = Inject(
    create(path.join(config.path, 'blobs')),
    Set(Level(path.join(config.path, 'blobs_push'), {valueEncoding: 'json'})),
    sbot.id
  )

  sbot.on('rpc:connect', function (rpc) {
    blobs._onConnect(rpc, rpc.id)
  })
  return blobs
}

<commit_msg>Ignore local client connection<commit_after>var create = require('./create')
var path = require('path')
var Inject = require('./inject')
var Set = require('./set')
var Level = require('level')

exports.manifest = {
  get: 'source',
  add: 'sink',
  ls: 'source',
  has: 'async',
  size: 'async',
  meta: 'async',
  want: 'async',
  push: 'async',
  changes: 'source',
  createWants: 'source'
}

exports.name = 'blobs'

exports.version = require('./package.json').version

exports.permissions = {
    anonymous: {allow: ['has', 'get', 'changes', 'createWants']},
}

exports.init = function (sbot, config) {
  var blobs = Inject(
    create(path.join(config.path, 'blobs')),
    Set(Level(path.join(config.path, 'blobs_push'), {valueEncoding: 'json'})),
    sbot.id
  )

  sbot.on('rpc:connect', function (rpc) {
    if (rpc.id === sbot.id) return
    blobs._onConnect(rpc, rpc.id)
  })
  return blobs
}

<|endoftext|>


<commit_before>'use strict';

var utils = require('./utils');

/**
 * Expose `Engines`
 */

module.exports = Engines;

/**
 * ```js
 * var Engines = require('engine-cache');
 * var engines = new Engines();
 * ```
 *
 * @param {Object} `engines` Optionally pass an object of engines to initialize with.
 * @api public
 */

function Engines(engines, options) {
  this.options = options || {};
  this.cache = engines || {};
  this.AsyncHelpers = this.options.AsyncHelpers || utils.AsyncHelpers;
  this.Helpers = this.options.Helpers || utils.Helpers;
}

/**
 * Register the given view engine callback `fn` as `ext`.
 *
 * ```js
 * var consolidate = require('consolidate')
 * engines.setEngine('hbs', consolidate.handlebars)
 * ```
 *
 * @param {String} `ext`
 * @param {Object|Function} `options` or callback `fn`.
 * @param {Function} `fn` Callback.
 * @return {Object} `Engines` to enable chaining.
 * @api public
 */

Engines.prototype.setEngine = function(ext, fn, options) {
  var engine = normalizeEngine(fn, options);
  var opts = engine.options;

  engine.helpers = new this.Helpers(opts);
  engine.asyncHelpers = new this.AsyncHelpers(opts);
  engine.name = utils.stripExt(engine.name || opts.name || ext);
  opts.ext = utils.formatExt(ext);

  // decorate wrapped methods for async helper handling
  decorate(engine);
  // add custom inspect method
  inspect(engine);

  // set the engine on the cache
  this.cache[opts.ext] = engine;
  return this;
};

/**
 * Add an object of engines onto `engines.cache`.
 *
 * ```js
 * engines.setEngines(require('consolidate'))
 * ```
 *
 * @param  {Object} `obj` Engines to load.
 * @return {Object} `Engines` to enable chaining.
 * @api public
 */

Engines.prototype.setEngines = function(engines) {
  for (var key in engines) {
    if (engines.hasOwnProperty(key) && key !== 'clearCache') {
      this.setEngine(key, engines[key]);
    }
  }
  return this;
};

/**
 * Return the engine stored by `ext`. If no `ext`
 * is passed, undefined is returned.
 *
 * ```js
 * var consolidate = require('consolidate');
 * var engine = engine.setEngine('hbs', consolidate.handlebars);
 *
 * var engine = engine.getEngine('hbs');
 * console.log(engine);
 * // => {render: [function], renderFile: [function]}
 * ```
 *
 * @param {String} `ext` The engine to get.
 * @return {Object} The specified engine.
 * @api public
 */

Engines.prototype.getEngine = function(ext) {
  var engine = ext ? this.cache[utils.formatExt(ext)] : null;
  if (!engine) {
    engine = this.options.defaultEngine;
    if (typeof engine === 'string') {
      engine = this.cache[utils.formatExt(engine)];
    }
  }
  return engine;
};

/**
 * Get and set helpers for the given `ext` (engine). If no
 * `ext` is passed, the entire helper cache is returned.
 *
 * **Example:**
 *
 * ```js
 * var helpers = engines.helpers('hbs');
 * helpers.addHelper('bar', function() {});
 * helpers.getEngineHelper('bar');
 * helpers.getEngineHelper();
 * ```
 *
 * See [helper-cache] for any related issues, API details, and documentation.
 *
 * @param {String} `ext` The helper cache to get and set to.
 * @return {Object} Object of helpers for the specified engine.
 * @api public
 */

Engines.prototype.helpers = function(ext) {
  var engine = this.getEngine(ext);
  if (engine) {
    return engine.helpers;
  }
};

/**
 * Normalize engine so that `.render` is a property on the `engine` object.
 */

function normalizeEngine(fn, options) {
  if (utils.isEngine(options)) {
    return normalizeEngine(options, fn); //<= reverse args
  }

  if (!utils.isObject(fn) && typeof fn !== 'function') {
    throw new TypeError('expected an object or function');
  }

  var engine = {};
  engine.render = fn.render || fn;
  engine.options = utils.extend({}, options);

  if (typeof engine.render !== 'function') {
    throw new Error('expected engine to have a render method');
  }

  for (var key in fn) {
    if (key === 'options') {
      engine.options = utils.merge({}, engine.options, fn[key]);
      continue;
    }
    if (key === '__express') {
      engine.renderFile = fn[key];
    }
    engine[key] = fn[key];
  }
  return engine;
}

/**
 * Wrap engines to extend the helpers object and other
 * native methods or functionality.
 *
 * ```js
 * engines.decorate(engine);
 * ```
 *
 * @param  {Object} `engine` The engine to wrap.
 * @return {Object} The wrapped engine.
 * @api private
 */

function decorate(engine) {
  // save a reference to original methods
  var renderSync = engine.renderSync;
  var render = engine.render;
  var compile = engine.compile;

  /**
   * Wrapped compile function for all engines loaded onto engine-cache.
   * If possible, compiles the string with the original engine's compile function.
   * Returns a render function that will either use the original engine's compiled function
   * or the `render/renderSync` methods and will resolve async helper ids.
   *
   * ```js
   * var fn = engine.compile('<%= upper(foo) %>', {imports: {'upper': upper}});
   * fn({foo: 'bar'}));
   * //=> BAR
   * ```
   *
   * @param  {String} `str` Original string to compile.
   * @param  {Object} `opts` Options/options to pass to engine's compile function. If a function is passed on `options.mergeFn`, that will be used for merging context before passing it to render.
   * @return {Function} Returns render function to call that takes `locals` and optional `callback` function.
   */

  engine.compile = function engineCompile(str, options) {
    if (typeof str === 'function') {
      return str;
    }

    if (typeof options !== 'undefined' && !utils.isObject(options)) {
      throw new TypeError('expected options to be an object or undefined');
    }

    options = utils.extend({}, options);
    var helpers = mergeHelpers(engine, options);
    var compiled = compile ? compile.call(engine, str, helpers) : null;

    return function(locals, cb) {
      if (typeof locals === 'function') {
        cb = locals;
        locals = {};
      }

      // if compiled already, we can delete helpers and partials from
      // the `helpers` object, since were bound to the context and
      // passed to the engine at compile time
      if (typeof compiled === 'function') {
        str = compiled;
        helpers = {};
      }

      var data = {};
      if (typeof locals === 'string' || Array.isArray(locals)) {
        data = locals;

      } else if (options && typeof options.mergeFn === 'function') {
        data = options.mergeFn(helpers, locals);

      } else {
        data = utils.merge({}, locals, helpers);
      }

      if (typeof cb !== 'function') {
        return renderSync.call(engine, str, data);
      }

      render.call(engine, str, data, function(err, str) {
        if (err) {
          cb(err);
          return;
        }
        engine.asyncHelpers.resolveIds(str, cb);
      });
    };
  };

  /**
   * Wrapped render function for all engines loaded onto engine-cache.
   * Compiles and renders strings with given context.
   *
   * ```js
   *  engine.render('<%= foo %>', {foo: 'bar'}, function(err, content) {
   *    //=> bar
   *  });
   * ```
   *
   * @param  {String|Function} `str` Original string to compile or function to use to render.
   * @param  {Object} `options` Options/locals to pass to compiled function for rendering.
   * @param {Function} `cb` Callback function that returns `err, content`.
   */

  engine.render = function engineRender(str, locals, cb) {
    if (typeof locals === 'function') {
      cb = locals;
      locals = {};
    }

    if (typeof cb !== 'function') {
      throw new TypeError('expected a callback function');
    }

    if (typeof str === 'function') {
      str(locals, cb);
      return;
    }

    if (typeof str !== 'string') {
      cb(new TypeError('expected a string or compiled function'));
      return;
    }

    var async = locals.async;
    locals.async = true;

    // compile the template to create a function
    var fn = this.compile(str, locals);

    // call the function to render templates
    fn(locals, function(err, content) {
      if (err) {
        cb(err);
        return;
      }
      // reset original `async` value
      locals.async = async;
      cb(null, content);
    });
  };

  /**
   * Wrapped renderSync function for all engines loaded onto engine-cache.
   * Compiles and renders strings with given context.
   *
   * ```js
   * engine.renderSync('<%= foo %>', {foo: 'bar'});
   * //=> bar
   * ```
   *
   * @param  {String|Function} `str` Original string to compile or function to use to render.
   * @param  {Object} `locals` Locals or options to pass to compiled function for rendering.
   * @return {String} Returns rendered content.
   */

  engine.renderSync = function wrappedRenderSync(str, locals) {
    if (typeof str === 'function') {
      return str(locals);
    }

    if (typeof str !== 'string') {
      throw new TypeError('expected a string or compiled function');
    }

    var context = utils.extend({}, locals);
    context.helpers = utils.merge({}, this.helpers, context.helpers);
    var render = this.compile(str, context);
    return render(context);
  };
}

/**
 * Add a custom inspect function onto the engine.
 */

function inspect(engine) {
  var inspect = ['"' + engine.name + '"'];
  var exts = utils.arrayify(engine.options.ext).join(', ');
  inspect.push('<ext "' + exts + '">');
  engine.inspect = function() {
    return '<Engine ' + inspect.join(' ') + '>';
  };
}

/**
 * Merge the local engine helpers with the options helpers.
 *
 * @param  {Object} `options` Options passed into `render` or `compile`
 * @return {Object} Options object with merged helpers
 */

function mergeHelpers(engine, options) {
  if (!options || typeof options !== 'object') {
    throw new TypeError('expected an object');
  }

  var opts = utils.extend({}, options);
  var helpers = utils.merge({}, engine.helpers, opts.helpers);

  for (var key in helpers) {
    if (helpers.hasOwnProperty(key)) {
      engine.asyncHelpers.set(key, helpers[key]);
    }
  }

  opts.helpers = engine.asyncHelpers.get({wrap: opts.async});
  return opts;
}
<commit_msg>__express<commit_after>'use strict';

var utils = require('./utils');

/**
 * Expose `Engines`
 */

module.exports = Engines;

/**
 * ```js
 * var Engines = require('engine-cache');
 * var engines = new Engines();
 * ```
 *
 * @param {Object} `engines` Optionally pass an object of engines to initialize with.
 * @api public
 */

function Engines(engines, options) {
  this.options = options || {};
  this.cache = engines || {};
  this.AsyncHelpers = this.options.AsyncHelpers || utils.AsyncHelpers;
  this.Helpers = this.options.Helpers || utils.Helpers;
}

/**
 * Register the given view engine callback `fn` as `ext`.
 *
 * ```js
 * var consolidate = require('consolidate')
 * engines.setEngine('hbs', consolidate.handlebars)
 * ```
 *
 * @param {String} `ext`
 * @param {Object|Function} `options` or callback `fn`.
 * @param {Function} `fn` Callback.
 * @return {Object} `Engines` to enable chaining.
 * @api public
 */

Engines.prototype.setEngine = function(ext, fn, options) {
  var engine = normalizeEngine(fn, options);
  var opts = engine.options;

  engine.helpers = new this.Helpers(opts);
  engine.asyncHelpers = new this.AsyncHelpers(opts);
  engine.name = utils.stripExt(engine.name || opts.name || ext);
  opts.ext = utils.formatExt(ext);

  // decorate wrapped methods for async helper handling
  decorate(engine);
  // add custom inspect method
  inspect(engine);

  // set the engine on the cache
  this.cache[opts.ext] = engine;
  return this;
};

/**
 * Add an object of engines onto `engines.cache`.
 *
 * ```js
 * engines.setEngines(require('consolidate'))
 * ```
 *
 * @param  {Object} `obj` Engines to load.
 * @return {Object} `Engines` to enable chaining.
 * @api public
 */

Engines.prototype.setEngines = function(engines) {
  for (var key in engines) {
    if (engines.hasOwnProperty(key) && key !== 'clearCache') {
      this.setEngine(key, engines[key]);
    }
  }
  return this;
};

/**
 * Return the engine stored by `ext`. If no `ext`
 * is passed, undefined is returned.
 *
 * ```js
 * var consolidate = require('consolidate');
 * var engine = engine.setEngine('hbs', consolidate.handlebars);
 *
 * var engine = engine.getEngine('hbs');
 * console.log(engine);
 * // => {render: [function], renderFile: [function]}
 * ```
 *
 * @param {String} `ext` The engine to get.
 * @return {Object} The specified engine.
 * @api public
 */

Engines.prototype.getEngine = function(ext) {
  var engine = ext ? this.cache[utils.formatExt(ext)] : null;
  if (!engine) {
    engine = this.options.defaultEngine;
    if (typeof engine === 'string') {
      engine = this.cache[utils.formatExt(engine)];
    }
  }
  return engine;
};

/**
 * Get and set helpers for the given `ext` (engine). If no
 * `ext` is passed, the entire helper cache is returned.
 *
 * **Example:**
 *
 * ```js
 * var helpers = engines.helpers('hbs');
 * helpers.addHelper('bar', function() {});
 * helpers.getEngineHelper('bar');
 * helpers.getEngineHelper();
 * ```
 *
 * See [helper-cache] for any related issues, API details, and documentation.
 *
 * @param {String} `ext` The helper cache to get and set to.
 * @return {Object} Object of helpers for the specified engine.
 * @api public
 */

Engines.prototype.helpers = function(ext) {
  var engine = this.getEngine(ext);
  if (engine) {
    return engine.helpers;
  }
};

/**
 * Normalize engine so that `.render` is a property on the `engine` object.
 */

function normalizeEngine(fn, options) {
  if (utils.isEngine(options)) {
    return normalizeEngine(options, fn); //<= reverse args
  }

  if (!utils.isObject(fn) && typeof fn !== 'function') {
    throw new TypeError('expected an object or function');
  }

  var engine = {};
  engine.render = fn.render || fn;
  engine.options = utils.extend({}, options);

  if (typeof engine.render !== 'function') {
    throw new Error('expected engine to have a render method');
  }

  for (var key in fn) {
    if (key === 'options') {
      engine.options = utils.merge({}, engine.options, fn[key]);
      continue;
    }
    if (key === '__express' && !fn.hasOwnProperty('renderFile')) {
      engine.renderFile = fn[key];
    }
    engine[key] = fn[key];
  }
  return engine;
}

/**
 * Wrap engines to extend the helpers object and other
 * native methods or functionality.
 *
 * ```js
 * engines.decorate(engine);
 * ```
 *
 * @param  {Object} `engine` The engine to wrap.
 * @return {Object} The wrapped engine.
 * @api private
 */

function decorate(engine) {
  // save a reference to original methods
  var renderSync = engine.renderSync;
  var render = engine.render;
  var compile = engine.compile;

  /**
   * Wrapped compile function for all engines loaded onto engine-cache.
   * If possible, compiles the string with the original engine's compile function.
   * Returns a render function that will either use the original engine's compiled function
   * or the `render/renderSync` methods and will resolve async helper ids.
   *
   * ```js
   * var fn = engine.compile('<%= upper(foo) %>', {imports: {'upper': upper}});
   * fn({foo: 'bar'}));
   * //=> BAR
   * ```
   *
   * @param  {String} `str` Original string to compile.
   * @param  {Object} `opts` Options/options to pass to engine's compile function. If a function is passed on `options.mergeFn`, that will be used for merging context before passing it to render.
   * @return {Function} Returns render function to call that takes `locals` and optional `callback` function.
   */

  engine.compile = function engineCompile(str, options) {
    if (typeof str === 'function') {
      return str;
    }

    if (typeof options !== 'undefined' && !utils.isObject(options)) {
      throw new TypeError('expected options to be an object or undefined');
    }

    options = utils.extend({}, options);
    var helpers = mergeHelpers(engine, options);
    var compiled = compile ? compile.call(engine, str, helpers) : null;

    return function(locals, cb) {
      if (typeof locals === 'function') {
        cb = locals;
        locals = {};
      }

      // if compiled already, we can delete helpers and partials from
      // the `helpers` object, since were bound to the context and
      // passed to the engine at compile time
      if (typeof compiled === 'function') {
        str = compiled;
        helpers = {};
      }

      var data = {};
      if (typeof locals === 'string' || Array.isArray(locals)) {
        data = locals;

      } else if (options && typeof options.mergeFn === 'function') {
        data = options.mergeFn(helpers, locals);

      } else {
        data = utils.merge({}, locals, helpers);
      }

      if (typeof cb !== 'function') {
        return renderSync.call(engine, str, data);
      }

      render.call(engine, str, data, function(err, str) {
        if (err) {
          cb(err);
          return;
        }
        engine.asyncHelpers.resolveIds(str, cb);
      });
    };
  };

  /**
   * Wrapped render function for all engines loaded onto engine-cache.
   * Compiles and renders strings with given context.
   *
   * ```js
   *  engine.render('<%= foo %>', {foo: 'bar'}, function(err, content) {
   *    //=> bar
   *  });
   * ```
   *
   * @param  {String|Function} `str` Original string to compile or function to use to render.
   * @param  {Object} `options` Options/locals to pass to compiled function for rendering.
   * @param {Function} `cb` Callback function that returns `err, content`.
   */

  engine.render = function engineRender(str, locals, cb) {
    if (typeof locals === 'function') {
      cb = locals;
      locals = {};
    }

    if (typeof cb !== 'function') {
      throw new TypeError('expected a callback function');
    }

    if (typeof str === 'function') {
      str(locals, cb);
      return;
    }

    if (typeof str !== 'string') {
      cb(new TypeError('expected a string or compiled function'));
      return;
    }

    var async = locals.async;
    locals.async = true;

    // compile the template to create a function
    var fn = this.compile(str, locals);

    // call the function to render templates
    fn(locals, function(err, content) {
      if (err) {
        cb(err);
        return;
      }
      // reset original `async` value
      locals.async = async;
      cb(null, content);
    });
  };

  /**
   * Wrapped renderSync function for all engines loaded onto engine-cache.
   * Compiles and renders strings with given context.
   *
   * ```js
   * engine.renderSync('<%= foo %>', {foo: 'bar'});
   * //=> bar
   * ```
   *
   * @param  {String|Function} `str` Original string to compile or function to use to render.
   * @param  {Object} `locals` Locals or options to pass to compiled function for rendering.
   * @return {String} Returns rendered content.
   */

  engine.renderSync = function wrappedRenderSync(str, locals) {
    if (typeof str === 'function') {
      return str(locals);
    }

    if (typeof str !== 'string') {
      throw new TypeError('expected a string or compiled function');
    }

    var context = utils.extend({}, locals);
    context.helpers = utils.merge({}, this.helpers, context.helpers);
    var render = this.compile(str, context);
    return render(context);
  };
}

/**
 * Add a custom inspect function onto the engine.
 */

function inspect(engine) {
  var inspect = ['"' + engine.name + '"'];
  var exts = utils.arrayify(engine.options.ext).join(', ');
  inspect.push('<ext "' + exts + '">');
  engine.inspect = function() {
    return '<Engine ' + inspect.join(' ') + '>';
  };
}

/**
 * Merge the local engine helpers with the options helpers.
 *
 * @param  {Object} `options` Options passed into `render` or `compile`
 * @return {Object} Options object with merged helpers
 */

function mergeHelpers(engine, options) {
  if (!options || typeof options !== 'object') {
    throw new TypeError('expected an object');
  }

  var opts = utils.extend({}, options);
  var helpers = utils.merge({}, engine.helpers, opts.helpers);

  for (var key in helpers) {
    if (helpers.hasOwnProperty(key)) {
      engine.asyncHelpers.set(key, helpers[key]);
    }
  }

  opts.helpers = engine.asyncHelpers.get({wrap: opts.async});
  return opts;
}
<|endoftext|>


<commit_before>require('dotenv').config();
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const path = require('path');
const jwt = require('express-jwt');

app.use(express.static('public'));

// Serve the front end app
app.get('/', (req, res) => {
  res.sendFile('index.html');
});

// MongoDB connection
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

const { DB_URL, DB_PORT, DB_NAME } = process.env;
mongoose.connect(
  `mongodb://${DB_URL}${DB_PORT ? ':' + DB_PORT : ''}/${DB_NAME}`
);

const db = mongoose.connection;
db.on('error', (error) => {
  throw new Error(error);
});
db.once('open', () => {
  console.log('Connected to mongo.')
});

// Graphql setup
const { graphqlExpress, graphiqlExpress } = require('graphql-server-express');
const { makeExecutableSchema } = require('graphql-tools');
const executableSchema = require('./src/server/graphql/data/schema');

// -- graphql endpoint
app.use(
  '/api',
  bodyParser.json(),
  jwt({
    secret: process.env.JWT_SECRET,
    credentialsRequired: false
  }),
  graphqlExpress(req => ({
    schema: executableSchema,
    context: { user: req.user || {} }
  }))
);

// -- graphiql endpoint
app.use('/graphiql', require('./src/server/graphiql'));

const PORT = process.env.PORT || 4444
app.listen(PORT);
console.log(`API up on port ${PORT}`);
<commit_msg>cleanup<commit_after>require('dotenv').config();
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const path = require('path');
const jwt = require('express-jwt');

app.use(express.static('public'));

// Serve the front end app
app.get('/', (req, res) => {
  res.sendFile('index.html');
});

// MongoDB connection
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

const { DB_URL, DB_PORT, DB_NAME } = process.env;
mongoose.connect(
  `mongodb://${DB_URL}${DB_PORT ? ':' + DB_PORT : ''}/${DB_NAME}`
);
mongoose.connection.on('error', (error) => {
  throw new Error(error);
});
mongoose.connection.once('open', () => {
  console.log('Connected to mongo.')
});

// Graphql setup
const { graphqlExpress, graphiqlExpress } = require('graphql-server-express');
const { makeExecutableSchema } = require('graphql-tools');
const executableSchema = require('./src/server/graphql/data/schema');

// -- graphql endpoint
app.use(
  '/api',
  bodyParser.json(),
  jwt({
    secret: process.env.JWT_SECRET,
    credentialsRequired: false
  }),
  graphqlExpress(req => ({
    schema: executableSchema,
    context: { user: req.user || {} }
  }))
);

// -- graphiql endpoint
app.use('/graphiql', require('./src/server/graphiql'));

const PORT = process.env.PORT || 4444
app.listen(PORT);
console.log(`API up on port ${PORT}`);
<|endoftext|>


<commit_before>var request       = require('request');
var uri           = 'https://api.ninja.is/rest/v0/';

exports.app = function(opts) {
  var access_token = opts.access_token;
  return {

    device: function(device) {

      return {

        /*
            Actuate a device
         */
        actuate: function(command,cb) {
          var opts = {
            url: uri + 'device/'+device,
            method: 'PUT',
            qs: { access_token:access_token },
            json: { DA:command }
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null)
              else cb({statusCode:b.id||200,error:b.error})
            }
          });
        },

        /**
         * Subscribe to the device's data feed
         * Optionally `overwrite` an existing callback url with the provided
         * `url`. Default is false.
         *
         * Example:
         *     app.device(guid).subscribe('example.com',true)
         *
         * @param {String} url
         * @param {Boolean} overwrite
         * @param {Function} cb
         * @api public
         */

        subscribe: function(url,overwrite,cb) {
          if (typeof overwrite==="function") {
            cb = overwrite;
            overwrite = false;
          }
          var opts = {
            url: uri + 'device/'+device+'/callback',
            method: 'POST',
            qs: { access_token:access_token },
            json: { url:url }
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null)
              else if (b.id===409 && overwrite) {
                // A url already exists, let's update it
                var opts = {
                  url: uri + 'device/'+device+'/callback',
                  method: 'PUT',
                  qs: { access_token:access_token },
                  json: { url:url }
                };
                request(opts,function(e,r,b) {
                  if (e) cb(e)
                  else {
                    if (b.result===1) cb(null)
                    else cb({statusCode:b.id||200,error:b.error})
                  }
                });
              }
              else {
                cb({statusCode:b.id||200,error:b.error})
              }
            }
          });
        },

        /*
            Fetch historical data
         */

        data: function(from, to, cb) {
          var qs = {access_token:access_token};

          if (typeof from === "function") {
            cb = from;
            from = false;
          } else if (typeof to === "function") {
            cb = to;
            to = false;
          }
          if (from instanceof Date) from = from.getTime();
          if (from) qs.from = from;
          if (to instanceof Date) to = to.getTime();
          if (to) qs.to = to;

          var opts = {
            url: uri + 'device/'+device+'/data',
            method: 'GET',
            qs: qs,
            json: true
          };

          request(opts,function(e,r,b) {
            console.dir(b);
            if (e) cb(e)
            else {
              if (b.result===1) cb(null, b.data)
              else cb({statusCode:b.id||200,error:b.error})
            }
          });
        },

        /*
            Fetch latest data
         */

        last_heartbeat: function(cb) {
          var opts = {
            url: uri + 'device/'+device+'/heartbeat',
            method: 'GET',
            qs: { access_token:access_token },
            json: true
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null, b.data)
              else cb({statusCode:b.id||200,error:b.error})
            }
          });
        }

      }

    },

    devices: function(cb) {
      var opts = {
        url: uri + 'devices',
        method: 'GET',
        qs: { access_token:access_token },
        json: true
      };
      request(opts,function(e,r,b) {
        if (e) cb(e)
          else {
            if (b.result===1) cb(null, b.data)
            else {
              cb({statusCode:b.id||200,error:b.error})
            }
          }
      });
    }
  }
}<commit_msg>More user functions<commit_after>var request       = require('request');
var uri           = 'https://api.ninja.is/rest/v0/';

exports.app = function(opts) {

  var access_token = opts.access_token;

  return {
    /**
     * Fetched all the user's information. If no callback is provided
     * then more specific information can be requested
     *
     * Example:
     *     app.user(function(err, data) { ... })
     *     app.user().stream(function(err,data){ ... })
     *
     * @param {Function} cb
     * @api public
     */
    user: function(cb) {
      if (typeof cb === "function") {
        var opts = {
          url: uri + 'user',
          method: 'GET',
          qs: { access_token:access_token },
          json: true
        };
        request(opts,function(e,r,b) {
          if (e) cb(e)
          else {
            if (r.statusCode==200) cb(null, b)
            else {
              cb({statusCode:r.statusCode,error:b.error})
            }
          }
        });
        return;
      }

      return {
        /**
         * Fetched the user's stream
         *
         * Example:
         *     app.user().stream(function(err,data){ ... })
         *
         * @param {Function} cb
         * @api public
         */
        stream: function(cb) {
          var opts = {
            url: uri + 'user/stream',
            method: 'GET',
            qs: { access_token:access_token },
            json: true
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (r.statusCode==200) cb(null, b)
              else {
                cb({statusCode:r.statusCode,error:b.error})
              }
            }
          });
        },
        /**
         * Fetches the user's pucher channel
         *
         * Example:
         *     app.user().pusher_channel(function(err,data){ ... })
         *
         * @param {Function} cb
         * @api public
         */
        pusher_channel: function(cb) {
          var opts = {
            url: uri + 'user/pusherchannel',
            method: 'GET',
            qs: { access_token:access_token },
            json: true
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (r.statusCode==200) cb(null, b.data)
              else {
                cb({statusCode:b.id||200,error:b.error})
              }
            }
          });
        },
      }
    },

    device: function(device) {

      return {
        /**
         * Actuates a device, sending a given `command`.
         *
         * Example:
         *     app.device(a_led_guid).actuate('FFFFFF',function(err) { ... })
         *
         * @param {String} command
         * @param {Function} cb
         * @api public
         */
        actuate: function(command,cb) {
          var opts = {
            url: uri + 'device/'+device,
            method: 'PUT',
            qs: { access_token:access_token },
            json: { DA:command }
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null)
              else cb({statusCode:b.id||200,error:b.error})
            }
          });
        },

        /**
         * Subscribes to a device's data feed.
         *
         * Optionally `overwrite`s an existing callback `url`
         * Default is false.
         *
         * Example:
         *     app.device(guid).subscribe('example.com',true,function(err) { ... })
         *
         * @param {String} url The url that Ninja Blocks will POST data to
         * @param {Boolean} overwrite If a callback url exists, this flag will force an overwrite
         * @param {Function} cb
         * @api public
         */
        subscribe: function(url,overwrite,cb) {
          if (typeof overwrite === "function") {
            cb = overwrite;
            overwrite = false;
          }
          var opts = {
            url: uri + 'device/'+device+'/callback',
            method: 'POST',
            qs: { access_token:access_token },
            json: { url:url }
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null)
              else if (b.id===409 && overwrite) {
                // A url already exists, let's update it
                var opts = {
                  url: uri + 'device/'+device+'/callback',
                  method: 'PUT',
                  qs: { access_token:access_token },
                  json: { url:url }
                };
                request(opts,function(e,r,b) {
                  if (e) cb(e)
                  else {
                    if (b.result===1) cb(null)
                    else cb({statusCode:b.id||200,error:b.error})
                  }
                });
              }
              else {
                cb({statusCode:b.id||200,error:b.error})
              }
            }
          });
        },

        /**
         * Unubscribes to a device's data feed.
         *
         * Example:
         *     app.device(guid).unsubscribe(function(err) { ... })
         *
         * @param {Function} cb
         * @api public
         */
        unsubscribe: function(cb) {
          var opts = {
            url: uri + 'device/'+device+'/callback',
            method: 'DELETE',
            qs: { access_token:access_token }
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null)
              else {
                cb({statusCode:b.id||200,error:b.error})
              }
            }
          });
        },

        /**
         * Fetches any historical data about this device.
         * Optionally specify the period's `start` and `end`
         * timestamp.
         *
         * Example:
         *     app.device(guid).data(start, end, function(err, data) { ... })
         *
         * @param {Integer|Date} start The timestamp/datetime of the beginning of the period
         * @param {Integer|Date} end the timestamp/datetime of the end of the period
         * @param {Function} cb
         * @api public
         */
        data: function(start, end, cb) {
          var qs = {access_token:access_token};

          if (typeof start === "function") {
            cb = start;
            start = false;
          } else if (typeof end === "function") {
            cb = end;
            end = false;
          }

          if (start instanceof Date) start = start.getTime();
          if (start) qs.from = start;
          if (end instanceof Date) end = end.getTime();
          if (end) qs.to = end;

          var opts = {
            url: uri + 'device/'+device+'/data',
            method: 'GET',
            qs: qs,
            json: true
          };

          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null, b.data)
              else cb({statusCode:b.id||200,error:b.error})
            }
          });
        },

        /**
         * Fetches the last heartbeat received by this device.
         *
         * Example:
         *     app.device(guid).last_heartbeat(function(err, data) { ... })
         *
         * @param {Function} cb
         * @api public
         */
        last_heartbeat: function(cb) {
          var opts = {
            url: uri + 'device/'+device+'/heartbeat',
            method: 'GET',
            qs: { access_token:access_token },
            json: true
          };
          request(opts,function(e,r,b) {
            if (e) cb(e)
            else {
              if (b.result===1) cb(null, b.data)
              else cb({statusCode:b.id||200,error:b.error})
            }
          });
        }

      }

    },
    /**
     * Fetched all the user's device details
     *
     * Example:
     *     app.devices(function(err, data) { ... })
     *
     * @param {Function} cb
     * @api public
     */
    devices: function(cb) {
      var opts = {
        url: uri + 'devices',
        method: 'GET',
        qs: { access_token:access_token },
        json: true
      };
      request(opts,function(e,r,b) {
        if (e) cb(e)
          else {
            if (b.result===1) cb(null, b.data)
            else {
              cb({statusCode:b.id||200,error:b.error})
            }
          }
      });
    }
  }
}<|endoftext|>


<commit_before>exports.render = render
exports.append = append
var mime = exports.mime = require('./lib/mime.json')

var debug = require('debug')('render-media')
var isAscii = require('is-ascii')
var MediaElementWrapper = require('mediasource')
var path = require('path')
var streamToBlobURL = require('stream-to-blob-url')
var videostream = require('videostream')

var VIDEOSTREAM_EXTS = [ '.mp4', '.m4v', '.m4a' ]

var MEDIASOURCE_VIDEO_EXTS = [ '.mp4', '.m4v', '.webm' ]
var MEDIASOURCE_AUDIO_EXTS = [ '.m4a', '.mp3' ]
var MEDIASOURCE_EXTS = MEDIASOURCE_VIDEO_EXTS.concat(MEDIASOURCE_AUDIO_EXTS)

var AUDIO_EXTS = [ '.wav', '.aac', '.ogg', '.oga' ]
var IMAGE_EXTS = [ '.jpg', '.jpeg', '.png', '.gif', '.bmp' ]
var IFRAME_EXTS = [ '.css', '.html', '.js', '.md', '.pdf', '.txt' ]

var MediaSource = typeof window !== 'undefined' && window.MediaSource

function render (file, elem, cb) {
  validateFile(file)
  if (typeof elem === 'string') elem = document.querySelector(elem)

  renderMedia(file, function (tagName) {
    if (elem.nodeName !== tagName.toUpperCase()) {
      var extname = path.extname(file.name).toLowerCase()

      throw new Error(
        'Cannot render "' + extname + '" inside a "' +
        elem.nodeName.toLowerCase() + '" element, expected "' + tagName + '"'
      )
    }

    return elem
  }, cb)
}

function append (file, rootElem, cb) {
  if (!cb) cb = function () {}
  validateFile(file)
  if (typeof rootElem === 'string') rootElem = document.querySelector(rootElem)

  if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) {
    throw new Error(
      'Invalid video/audio node argument. Argument must be root element that ' +
      'video/audio tag will be appended to.'
    )
  }

  renderMedia(file, function (tagName) {
    if (tagName === 'video' || tagName === 'audio') return createMedia(tagName)
    else return createElem(tagName)
  }, function (err, elem) {
    if (err && elem) elem.remove()
    cb(err, elem)
  })

  function createMedia (tagName) {
    var elem = createElem(tagName)
    elem.controls = true
    elem.autoplay = true // for chrome
    elem.play() // for firefox
    rootElem.appendChild(elem)
    return elem
  }

  function createElem (tagName) {
    var elem = document.createElement(tagName)
    rootElem.appendChild(elem)
    return elem
  }
}

function renderMedia (file, getElem, cb) {
  if (!cb) cb = function () {}
  var extname = path.extname(file.name).toLowerCase()
  var currentTime = 0
  var elem

  if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) {
    renderMediaSource()
  } else if (AUDIO_EXTS.indexOf(extname) >= 0) {
    renderAudio()
  } else if (IMAGE_EXTS.indexOf(extname) >= 0) {
    renderImage()
  } else if (IFRAME_EXTS.indexOf(extname) >= 0) {
    renderIframe()
  } else {
    tryRenderIframe()
  }

  function renderMediaSource () {
    var tagName = MEDIASOURCE_VIDEO_EXTS.indexOf(extname) >= 0 ? 'video' : 'audio'

    if (MediaSource) {
      if (VIDEOSTREAM_EXTS.indexOf(extname) >= 0) {
        useVideostream()
      } else {
        useMediaSource()
      }
    } else {
      useBlobURL()
    }

    function useVideostream () {
      debug('Use `videostream` package for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToMediaSource)
      elem.addEventListener('playing', onPlaying)
      videostream(file, elem)
    }

    function useMediaSource () {
      debug('Use MediaSource API for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToBlobURL)
      elem.addEventListener('playing', onPlaying)

      var wrapper = new MediaElementWrapper(elem)
      var writable = wrapper.createWriteStream(getCodec(file.name))
      file.createReadStream().pipe(writable)

      if (currentTime) elem.currentTime = currentTime
    }

    function useBlobURL () {
      debug('Use Blob URL for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fatalError)
      elem.addEventListener('playing', onPlaying)
      getBlobURL(file, function (err, url) {
        if (err) return fatalError(err)
        elem.src = url
        if (currentTime) elem.currentTime = currentTime
      })
    }

    function fallbackToMediaSource (err) {
      debug('videostream error: fallback to MediaSource API: %o', err.message || err)
      elem.removeEventListener('error', fallbackToMediaSource)
      elem.removeEventListener('playing', onPlaying)

      useMediaSource()
    }

    function fallbackToBlobURL (err) {
      debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)
      elem.removeEventListener('error', fallbackToBlobURL)
      elem.removeEventListener('playing', onPlaying)

      useBlobURL()
    }

    function prepareElem () {
      if (!elem) {
        elem = getElem(tagName)

        elem.addEventListener('progress', function () {
          currentTime = elem.currentTime
        })
      }
    }
  }

  function onPlaying () {
    elem.removeEventListener('playing', onPlaying)
    cb(null, elem)
  }

  function renderAudio () {
    elem = getElem('audio')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.addEventListener('error', fatalError)
      elem.addEventListener('playing', onPlaying)
      elem.src = url
    })
  }

  function renderImage () {
    elem = getElem('img')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      elem.alt = file.name
      cb(null, elem)
    })
  }

  function renderIframe () {
    elem = getElem('iframe')

    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts'
      cb(null, elem)
    })
  }

  function tryRenderIframe () {
    debug('Unknown file extension "%s" - will attempt to render into iframe', extname)

    var str = ''
    file.createReadStream({ start: 0, end: 1000 })
      .setEncoding('utf8')
      .on('data', function (chunk) {
        str += chunk
      })
      .on('end', done)
      .on('error', cb)

    function done () {
      if (isAscii(str)) {
        debug('File extension "%s" appears ascii, so will render.', extname)
        renderIframe()
      } else {
        debug('File extension "%s" appears non-ascii, will not render.', extname)
        cb(new Error('Unsupported file type "' + extname + '": Cannot append to DOM'))
      }
    }
  }

  function fatalError (err) {
    err.message = 'Error rendering file "' + file.name + '": ' + err.message
    debug(err.message)
    cb(err)
  }
}

function getBlobURL (file, cb) {
  var extname = path.extname(file.name).toLowerCase()
  streamToBlobURL(file.createReadStream(), mime[extname], cb)
}

function validateFile (file) {
  if (file == null) {
    throw new Error('file cannot be null or undefined')
  }
  if (typeof file.name !== 'string') {
    throw new Error('missing or invalid file.name property')
  }
  if (typeof file.createReadStream !== 'function') {
    throw new Error('missing or invalid file.createReadStream property')
  }
}

function getCodec (name) {
  var extname = path.extname(name).toLowerCase()
  return {
    '.m4a': 'audio/mp4; codecs="mp4a.40.5"',
    '.m4v': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.mp3': 'audio/mpeg',
    '.mp4': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.webm': 'video/webm; codecs="vorbis, vp8"'
  }[extname]
}
<commit_msg>Try to play .mkv<commit_after>exports.render = render
exports.append = append
var mime = exports.mime = require('./lib/mime.json')

var debug = require('debug')('render-media')
var isAscii = require('is-ascii')
var MediaElementWrapper = require('mediasource')
var path = require('path')
var streamToBlobURL = require('stream-to-blob-url')
var videostream = require('videostream')

var VIDEOSTREAM_EXTS = [ '.mp4', '.m4v', '.m4a' ]

var MEDIASOURCE_VIDEO_EXTS = [ '.mp4', '.m4v', '.webm', '.mkv' ]
var MEDIASOURCE_AUDIO_EXTS = [ '.m4a', '.mp3' ]
var MEDIASOURCE_EXTS = MEDIASOURCE_VIDEO_EXTS.concat(MEDIASOURCE_AUDIO_EXTS)

var AUDIO_EXTS = [ '.wav', '.aac', '.ogg', '.oga' ]
var IMAGE_EXTS = [ '.jpg', '.jpeg', '.png', '.gif', '.bmp' ]
var IFRAME_EXTS = [ '.css', '.html', '.js', '.md', '.pdf', '.txt' ]

var MediaSource = typeof window !== 'undefined' && window.MediaSource

function render (file, elem, cb) {
  validateFile(file)
  if (typeof elem === 'string') elem = document.querySelector(elem)

  renderMedia(file, function (tagName) {
    if (elem.nodeName !== tagName.toUpperCase()) {
      var extname = path.extname(file.name).toLowerCase()

      throw new Error(
        'Cannot render "' + extname + '" inside a "' +
        elem.nodeName.toLowerCase() + '" element, expected "' + tagName + '"'
      )
    }

    return elem
  }, cb)
}

function append (file, rootElem, cb) {
  if (!cb) cb = function () {}
  validateFile(file)
  if (typeof rootElem === 'string') rootElem = document.querySelector(rootElem)

  if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) {
    throw new Error(
      'Invalid video/audio node argument. Argument must be root element that ' +
      'video/audio tag will be appended to.'
    )
  }

  renderMedia(file, function (tagName) {
    if (tagName === 'video' || tagName === 'audio') return createMedia(tagName)
    else return createElem(tagName)
  }, function (err, elem) {
    if (err && elem) elem.remove()
    cb(err, elem)
  })

  function createMedia (tagName) {
    var elem = createElem(tagName)
    elem.controls = true
    elem.autoplay = true // for chrome
    elem.play() // for firefox
    rootElem.appendChild(elem)
    return elem
  }

  function createElem (tagName) {
    var elem = document.createElement(tagName)
    rootElem.appendChild(elem)
    return elem
  }
}

function renderMedia (file, getElem, cb) {
  if (!cb) cb = function () {}
  var extname = path.extname(file.name).toLowerCase()
  var currentTime = 0
  var elem

  if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) {
    renderMediaSource()
  } else if (AUDIO_EXTS.indexOf(extname) >= 0) {
    renderAudio()
  } else if (IMAGE_EXTS.indexOf(extname) >= 0) {
    renderImage()
  } else if (IFRAME_EXTS.indexOf(extname) >= 0) {
    renderIframe()
  } else {
    tryRenderIframe()
  }

  function renderMediaSource () {
    var tagName = MEDIASOURCE_VIDEO_EXTS.indexOf(extname) >= 0 ? 'video' : 'audio'

    if (MediaSource) {
      if (VIDEOSTREAM_EXTS.indexOf(extname) >= 0) {
        useVideostream()
      } else {
        useMediaSource()
      }
    } else {
      useBlobURL()
    }

    function useVideostream () {
      debug('Use `videostream` package for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToMediaSource)
      elem.addEventListener('playing', onPlaying)
      videostream(file, elem)
    }

    function useMediaSource () {
      debug('Use MediaSource API for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToBlobURL)
      elem.addEventListener('playing', onPlaying)

      var wrapper = new MediaElementWrapper(elem)
      var writable = wrapper.createWriteStream(getCodec(file.name))
      file.createReadStream().pipe(writable)

      if (currentTime) elem.currentTime = currentTime
    }

    function useBlobURL () {
      debug('Use Blob URL for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fatalError)
      elem.addEventListener('playing', onPlaying)
      getBlobURL(file, function (err, url) {
        if (err) return fatalError(err)
        elem.src = url
        if (currentTime) elem.currentTime = currentTime
      })
    }

    function fallbackToMediaSource (err) {
      debug('videostream error: fallback to MediaSource API: %o', err.message || err)
      elem.removeEventListener('error', fallbackToMediaSource)
      elem.removeEventListener('playing', onPlaying)

      useMediaSource()
    }

    function fallbackToBlobURL (err) {
      debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)
      elem.removeEventListener('error', fallbackToBlobURL)
      elem.removeEventListener('playing', onPlaying)

      useBlobURL()
    }

    function prepareElem () {
      if (!elem) {
        elem = getElem(tagName)

        elem.addEventListener('progress', function () {
          currentTime = elem.currentTime
        })
      }
    }
  }

  function onPlaying () {
    elem.removeEventListener('playing', onPlaying)
    cb(null, elem)
  }

  function renderAudio () {
    elem = getElem('audio')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.addEventListener('error', fatalError)
      elem.addEventListener('playing', onPlaying)
      elem.src = url
    })
  }

  function renderImage () {
    elem = getElem('img')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      elem.alt = file.name
      cb(null, elem)
    })
  }

  function renderIframe () {
    elem = getElem('iframe')

    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts'
      cb(null, elem)
    })
  }

  function tryRenderIframe () {
    debug('Unknown file extension "%s" - will attempt to render into iframe', extname)

    var str = ''
    file.createReadStream({ start: 0, end: 1000 })
      .setEncoding('utf8')
      .on('data', function (chunk) {
        str += chunk
      })
      .on('end', done)
      .on('error', cb)

    function done () {
      if (isAscii(str)) {
        debug('File extension "%s" appears ascii, so will render.', extname)
        renderIframe()
      } else {
        debug('File extension "%s" appears non-ascii, will not render.', extname)
        cb(new Error('Unsupported file type "' + extname + '": Cannot append to DOM'))
      }
    }
  }

  function fatalError (err) {
    err.message = 'Error rendering file "' + file.name + '": ' + err.message
    debug(err.message)
    cb(err)
  }
}

function getBlobURL (file, cb) {
  var extname = path.extname(file.name).toLowerCase()
  streamToBlobURL(file.createReadStream(), mime[extname], cb)
}

function validateFile (file) {
  if (file == null) {
    throw new Error('file cannot be null or undefined')
  }
  if (typeof file.name !== 'string') {
    throw new Error('missing or invalid file.name property')
  }
  if (typeof file.createReadStream !== 'function') {
    throw new Error('missing or invalid file.createReadStream property')
  }
}

function getCodec (name) {
  var extname = path.extname(name).toLowerCase()
  return {
    '.m4a': 'audio/mp4; codecs="mp4a.40.5"',
    '.m4v': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.mkv': 'video/webm; codecs="avc1.640029, mp4a.40.5"',
    '.mp3': 'audio/mpeg',
    '.mp4': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.webm': 'video/webm; codecs="vorbis, vp8"'
  }[extname]
}
<|endoftext|>


<commit_before>/** @jsx React.DOM */
'use strict';

jest.autoMockOff();

// Fixes https://github.com/facebook/jest/issues/78
jest.dontMock('react');
jest.dontMock('underscore');

describe('Software', function() {
    var React, TestUtils, Software, publication, context, _;

    beforeEach(function() {
        React = require('react');
        TestUtils = require('react/lib/ReactTestUtils');
        _ = require('underscore');

        // Set up context object to be rendered
        Software = require('../software').Software;
        context = require('../testdata/software');
    });

    describe('Software object with single references', function() {
        var software, summary;

        beforeEach(function() {
            // Render publication panel into jsnode
            software = <Software context={context} />;
            TestUtils.renderIntoDocument(software);

            summary = TestUtils.scryRenderedDOMComponentsWithClass(software, 'key-value');
        });

        it('has a title with link to software source', function() {
            var item = summary[0].getDOMNode().querySelector('[data-test="title"]');
            var itemDescription = item.getElementsByTagName('dd')[0];
            var anchor = itemDescription.getElementsByTagName('a')[0];
            expect(itemDescription.textContent).toEqual('HaploReg');
            expect(anchor.getAttribute('href')).toEqual('http://www.broadinstitute.org/mammals/haploreg/haploreg.php');
        });

        it('has a good description, software type, and used for', function() {
            var item = summary[0].getDOMNode().querySelector('[data-test="description"]');
            var itemDescription = item.getElementsByTagName('dd')[0];
            expect(itemDescription.textContent).toContain('Explores annotations of the noncoding genome');

            item = summary[0].getDOMNode().querySelector('[data-test="type"]');
            itemDescription = item.getElementsByTagName('dd')[0];
            expect(itemDescription.textContent).toEqual('database, variant annotation');

            item = summary[0].getDOMNode().querySelector('[data-test="purpose"]');
            itemDescription = item.getElementsByTagName('dd')[0];
            expect(itemDescription.textContent).toEqual('community resource');
        });
    });

    describe('Software object with single references', function() {
        var software, summary;

        beforeEach(function() {
            var context_ref = _.clone(context);
            context_ref.references = [require('../testdata/publication')];
            context_ref.references[0].references = ['PMID:19352372', 'PMCID:PMC3062402'];

            // Render publication panel into jsnode
            software = <Software context={context_ref} />;
            TestUtils.renderIntoDocument(software);

            summary = TestUtils.scryRenderedDOMComponentsWithClass(software, 'key-value');
        });

        it('has two references with proper links', function() {
            var item = summary[0].getDOMNode().querySelector('[data-test="references"]');
            var itemDescription = item.getElementsByTagName('dd')[0];
            var ul = itemDescription.getElementsByTagName('ul')[0];
            var lis = ul.getElementsByTagName('li');
            expect(lis.length).toEqual(2);

            var anchor = lis[0].getElementsByTagName('a')[0];
            expect(anchor.textContent).toEqual('PMID:19352372');
            expect(anchor.getAttribute('href')).toEqual('http://www.ncbi.nlm.nih.gov/pubmed/?term=19352372');

            anchor = lis[1].getElementsByTagName('a')[0];
            expect(anchor.textContent).toEqual('PMCID:PMC3062402');
            expect(anchor.getAttribute('href')).toEqual('http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3062402');
        });
    });
});
<commit_msg>Remove old comments from software Jest test.<commit_after>/** @jsx React.DOM */
'use strict';

jest.autoMockOff();

// Fixes https://github.com/facebook/jest/issues/78
jest.dontMock('react');
jest.dontMock('underscore');

describe('Software', function() {
    var React, TestUtils, Software, publication, context, _;

    beforeEach(function() {
        React = require('react');
        TestUtils = require('react/lib/ReactTestUtils');
        _ = require('underscore');

        // Set up context object to be rendered
        Software = require('../software').Software;
        context = require('../testdata/software');
    });

    describe('Software object with no references', function() {
        var software, summary;

        beforeEach(function() {
            software = <Software context={context} />;
            TestUtils.renderIntoDocument(software);

            summary = TestUtils.scryRenderedDOMComponentsWithClass(software, 'key-value');
        });

        it('has a title with link to software source', function() {
            var item = summary[0].getDOMNode().querySelector('[data-test="title"]');
            var itemDescription = item.getElementsByTagName('dd')[0];
            var anchor = itemDescription.getElementsByTagName('a')[0];
            expect(itemDescription.textContent).toEqual('HaploReg');
            expect(anchor.getAttribute('href')).toEqual('http://www.broadinstitute.org/mammals/haploreg/haploreg.php');
        });

        it('has a good description, software type, and used for', function() {
            var item = summary[0].getDOMNode().querySelector('[data-test="description"]');
            var itemDescription = item.getElementsByTagName('dd')[0];
            expect(itemDescription.textContent).toContain('Explores annotations of the noncoding genome');

            item = summary[0].getDOMNode().querySelector('[data-test="type"]');
            itemDescription = item.getElementsByTagName('dd')[0];
            expect(itemDescription.textContent).toEqual('database, variant annotation');

            item = summary[0].getDOMNode().querySelector('[data-test="purpose"]');
            itemDescription = item.getElementsByTagName('dd')[0];
            expect(itemDescription.textContent).toEqual('community resource');
        });
    });

    describe('Software object with single references', function() {
        var software, summary;

        beforeEach(function() {
            var context_ref = _.clone(context);
            context_ref.references = [require('../testdata/publication')];
            context_ref.references[0].references = ['PMID:19352372', 'PMCID:PMC3062402'];

            software = <Software context={context_ref} />;
            TestUtils.renderIntoDocument(software);

            summary = TestUtils.scryRenderedDOMComponentsWithClass(software, 'key-value');
        });

        it('has two references with proper links', function() {
            var item = summary[0].getDOMNode().querySelector('[data-test="references"]');
            var itemDescription = item.getElementsByTagName('dd')[0];
            var ul = itemDescription.getElementsByTagName('ul')[0];
            var lis = ul.getElementsByTagName('li');
            expect(lis.length).toEqual(2);

            var anchor = lis[0].getElementsByTagName('a')[0];
            expect(anchor.textContent).toEqual('PMID:19352372');
            expect(anchor.getAttribute('href')).toEqual('http://www.ncbi.nlm.nih.gov/pubmed/?term=19352372');

            anchor = lis[1].getElementsByTagName('a')[0];
            expect(anchor.textContent).toEqual('PMCID:PMC3062402');
            expect(anchor.getAttribute('href')).toEqual('http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3062402');
        });
    });
});
<|endoftext|>


<commit_before>var Bundler = require('./lib/bundler');

module.exports = function(config) {

    return new Bundler(config);
};
<commit_msg>exposing browserify lib<commit_after>var Bundler = require('./lib/bundler');

module.exports = function(config) {

    return new Bundler(config);
};

// expose browserify lib
exports.browserify = require('watchify').browserify
<|endoftext|>