<commit_before>'use strict';

var debug = require('diagnostics')('fever')
  , EventEmitter = require('eventemitter3')
  , TickTock = require('tick-tock')
  , destroy = require('demolish')
  , HotPath = require('hotpath')
  , parse = require('url').parse
  , fuse = require('fusing')
  , File = require('./file');

/**
 * Our file factory.
 *
 * Options:
 *
 * - hotpath, {Object}, Configuration for our hotpath cache.
 * - engine, {FileSystem}, The file system where we store and get our files.
 *
 * @constructor
 * @param {Object} options Fever configuration.
 * @api private
 */
function Fever(options) {
  if (!this) return new Fever(options);

  var selfie = this;
  options = options || {};

  this.fs = options.engine || require('supreme');   // File system.
  this.hotpath = new HotPath(options.hotpath);      // Internal cache system.
  this.timers = new TickTock(this);                 // Timer management.
  this.options = options;                           // Backup of the options.
  this.files = [];                                  // Active files.

  //
  // Expose the File constructor which now contains a reference to the newly
  // created Fever.
  //
  this.File = function File(path, options) {
    this.fuse([selfie, path, options]);
  };

  fuse(this.File, File);
}

//
// Supply provides our middleware and plugin system, so we're going to inherit
// from it.
//
Fever.prototype.__proto__ = require('supply').prototype;
Object.keys(EventEmitter.prototype).forEach(function each(key) {
  Fever.prototype[key] = EventEmitter.prototype[key];
});

/**
 * Handy helper function for creating optional callbacks.
 *
 * @param {Function} fn Optional callback.
 * @param {String} msg Optional failure message.
 * @returns {Function}
 * @api private
 */
Fever.prototype.optional = function optional(fn, msg) {
  return fn || function nope(err) {
    if (err) debug(msg || 'Missing callback for failed operation', err);
  };
};

/**
 * Replace the internal file system.
 *
 * @param {FileSystem} fs The file system that we should use for the files.
 * @returns {Fever}
 * @api public
 */
Fever.prototype.engine = function engine(fs) {
  this.fs = fs;

  return this;
};

/**
 * Get the files that use this path.
 *
 * @param {String} path location of file.
 * @returns {Array}
 * @api private
 */
Fever.prototype.get = function get(path) {
  return [];
};

/**
 * Re-cache the hot cache with the most requested files from this system.
 * Every time a file is requested we increment the requested count.
 *
 * @param {Function} fn Optional completion callback.
 * @returns {Fever}
 * @api public
 */
Fever.prototype.cache = function cache(fn) {
  fn = this.optional(fn, 'Failed to update the cache');

  var sorted = this.files.sort(function sort(a, b) {
    return a.requested - b.requested;
  });

  //
  // Clear the hot cache as we're about to refill it's contents with new and
  // potentially hotter code paths.
  //
  this.hotpath.reset();

  sorted.forEach(function forEach(file) {
    return this.hotpath.set(file.uuid, file.buffer());
  }, this);

  return this;
};

/**
 * Attempt to mount the factory to a given HTTP server instance. If no server is
 * given we will return a middleware layer that is compatible with connect.
 *
 * @param {HTTPServer} server A HTTP server which understands middleware.
 * @returns {Function} The middleware layer we've generated.
 * @api public
 */
Fever.prototype.mount = function mount(server, options) {
  var selfie = this;

  function fever(req, res, next) {
    req.uri = req.uri || parse(req.url);

    var file = selfie.alias(req.uri.pathname);
    if (!file || 'GET' !== req.method) return next();

    file.forward(res, { gzip: req.zipline, headers: req.headers });
  }

  if (server && 'function' === typeof server.use) {
    server.use('zipline', require('zipline'), options);
    server.use('fever', fever);
  }

  return fever;
};

/**
 * Destroy and clean-up things.
 *
 * @TODO cleanup Supply based data.
 * @TODO cleanup EventEmitter properties.
 *
 * @type {Function}
 * @returns {Boolean}
 * @api public
 */
Fever.prototype.destroy = destroy('fs, hotpath, timers, options, files');

//
// Expose the module.
//
Fever.File = File;
module.exports = Fever;
<commit_msg>[major] Added missing initialization<commit_after>'use strict';

var debug = require('diagnostics')('fever')
  , EventEmitter = require('eventemitter3')
  , TickTock = require('tick-tock')
  , destroy = require('demolish')
  , HotPath = require('hotpath')
  , parse = require('url').parse
  , fuse = require('fusing')
  , File = require('./file');

/**
 * Our file factory.
 *
 * Options:
 *
 * - hotpath, {Object}, Configuration for our hotpath cache.
 * - engine, {FileSystem}, The file system where we store and get our files.
 *
 * @constructor
 * @param {Object} options Fever configuration.
 * @api private
 */
function Fever(options) {
  if (!this) return new Fever(options);

  var selfie = this;
  options = options || {};

  this.fs = options.engine || require('supreme');   // File system like API.
  this.hotpath = new HotPath(options.hotpath);      // Internal cache system.
  this.timers = new TickTock(this);                 // Timer management.
  this.options = options;                           // Backup of the options.
  this.files = [];                                  // Active files.

  //
  // Expose the File constructor which now contains a reference to the newly
  // created Fever.
  //
  this.File = function File(path, options) {
    this.fuse([selfie, path, options]);
  };

  fuse(this.File, File);
  this.initialize();
}

//
// Supply provides our middleware and plugin system, so we're going to inherit
// from it.
//
Fever.prototype.__proto__ = require('supply').prototype;
Object.keys(EventEmitter.prototype).forEach(function each(key) {
  Fever.prototype[key] = EventEmitter.prototype[key];
});

/**
 * Initialize the Fever instance and initialize all the things.
 *
 * @api private
 */
Fever.prototype.initialize = function initialize() {
  this.on('add', function add(file) {
    this.files.push(file);
  });

  this.on('remove', function remove(file) {
    var index = this.files.indexOf(file);

    if (index === -1) return;
    this.files.splice(index, 0);
  });
};

/**
 * Handy helper function for creating optional callbacks.
 *
 * @param {Function} fn Optional callback.
 * @param {String} msg Optional failure message.
 * @returns {Function}
 * @api private
 */
Fever.prototype.optional = function optional(fn, msg) {
  return fn || function nope(err) {
    if (err) debug(msg || 'Missing callback for failed operation', err);
  };
};

/**
 * Replace the internal file system.
 *
 * @param {FileSystem} fs The file system that we should use for the files.
 * @returns {Fever}
 * @api public
 */
Fever.prototype.engine = function engine(fs) {
  this.fs = fs;

  return this;
};

/**
 * Get the files that use this path.
 *
 * @param {String} path location of file.
 * @returns {Array}
 * @api private
 */
Fever.prototype.get = function get(path) {
  return [];
};

/**
 * Add a new file to our collection, only if it doesn't exist before.
 *
 * @param {String} path Location of the file.
 * @param {Object} options File configuration.
 * @returns {Fever}
 * @api public
 */
Fever.prototype.add = function add(path, options) {
  if (this.files.some(function some(file) {
    return file.contains(path);
  })) return this;

  new this.File(path, options);

  return this;
};

/**
 * Re-cache the hot cache with the most requested files from this system.
 * Every time a file is requested we increment the requested count.
 *
 * @param {Function} fn Optional completion callback.
 * @returns {Fever}
 * @api public
 */
Fever.prototype.cache = function cache(fn) {
  fn = this.optional(fn, 'Failed to update the cache');

  var sorted = this.files.sort(function sort(a, b) {
    return a.requested - b.requested;
  });

  //
  // Clear the hot cache as we're about to refill it's contents with new and
  // potentially hotter code paths.
  //
  this.hotpath.reset();

  sorted.forEach(function forEach(file) {
    return this.hotpath.set(file.uuid, file.buffer());
  }, this);

  return this;
};

/**
 * Attempt to mount the factory to a given HTTP server instance. If no server is
 * given we will return a middleware layer that is compatible with connect.
 *
 * @param {HTTPServer} server A HTTP server which understands middleware.
 * @returns {Function} The middleware layer we've generated.
 * @api public
 */
Fever.prototype.mount = function mount(server, options) {
  var selfie = this;

  function fever(req, res, next) {
    req.uri = req.uri || parse(req.url);

    var file = selfie.alias(req.uri.pathname);
    if (!file || 'GET' !== req.method) return next();

    file.forward(res, { gzip: req.zipline, headers: req.headers });
  }

  if (server && 'function' === typeof server.use) {
    server.use('zipline', require('zipline'), options);
    server.use('fever', fever);
  }

  return fever;
};

/**
 * Destroy and clean-up things.
 *
 * @TODO cleanup Supply based data.
 * @TODO cleanup EventEmitter properties.
 *
 * @type {Function}
 * @returns {Boolean}
 * @api public
 */
Fever.prototype.destroy = destroy('fs, hotpath, timers, options, files');

//
// Expose the module.
//
Fever.File = File;
module.exports = Fever;
<|endoftext|>


<commit_before>import classNames from 'classnames';
import React from 'react';
import ReactDOM from 'react-dom';

import BindMixin from '../Mixin/BindMixin';
import Util from '../Util/Util';

class ItemCheckbox extends Util.mixin(BindMixin) {
  get methodsToBind() {
    return ['handleChange'];
  }

  componentDidMount() {
    super.componentDidMount(...arguments);
    this.updateCheckbox();
  }

  componentDidUpdate() {
    super.componentDidUpdate(...arguments);
    this.updateCheckbox();
  }

  updateCheckbox() {
    let {props, refs} = this;
    let checkbox = ReactDOM.findDOMNode(refs.checkbox);

    if (props.checked != null) {
      checkbox.checked = props.checked;
    }

    let indeterminate = props.indeterminate;
    if (indeterminate != null) {
      checkbox.indeterminate = indeterminate;
    }
  }

  handleChange(event) {
    this.props.handleEvent(
      'change',
      this.props.name,
      {
        checked: event.target.checked,
        indeterminate: event.target.indeterminate
      },
      event
    );
  }

  getLabel() {
    let label = this.props.label;
    if (!label) {
      return null;
    }

    return (

        {label}

    );
  }

  render() {
    let {props} = this;

    let labelClass = classNames({
      'form-row-element form-element-checkbox': true,
      [props.labelClass]: true
    });

    return (

        <input
          onChange={this.handleChange}
          disabled={props.disabled}
          ref="checkbox"
          type="checkbox" />

          <svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
            <g className="icon icon-svg-checkbox-indeterminate">
              <path d="M5,9.75 L11,9.75 C11.4142136,9.75 11.75,9.41421356 11.75,9 C11.75,8.58578644 11.4142136,8.25 11,8.25 L5,8.25 C4.58578644,8.25 4.25,8.58578644 4.25,9 C4.25,9.41421356 4.58578644,9.75 5,9.75 L5,9.75 Z" fill="#000000" fillOpacity="0.13"></path>
              <path d="M5,8.75 L11,8.75 C11.4142136,8.75 11.75,8.41421356 11.75,8 C11.75,7.58578644 11.4142136,7.25 11,7.25 L5,7.25 C4.58578644,7.25 4.25,7.58578644 4.25,8 C4.25,8.41421356 4.58578644,8.75 5,8.75 L5,8.75 Z" fill="#ffffff"></path>
            </g>
            <g className="icon icon-svg-checkbox-checked">
              <path d="M6.37547375,12.4433526 C6.66651906,12.8810343 7.30583183,12.8913338 7.61082475,12.4632544 L12.0274757,6.26416941 C12.2678262,5.92682021 12.1891933,5.45850202 11.8518441,5.21815145 C11.5144949,4.97780088 11.0461767,5.0564338 10.8058262,5.393783 L7.02648971,10.7134266 L5.62452625,8.60511675 C5.39516713,8.26020042 4.92962491,8.1665228 4.58470858,8.39588191 C4.23979226,8.62524103 4.14611463,9.09078326 4.37547375,9.43569958 L6.37547375,12.4433526 Z" fill="#000000" fillOpacity="0.13"></path>
              <path d="M6.37547375,11.4433526 C6.66651906,11.8810343 7.30583183,11.8913338 7.61082475,11.4632544 L12.0274757,5.26416941 C12.2678262,4.92682021 12.1891933,4.45850202 11.8518441,4.21815145 C11.5144949,3.97780088 11.0461767,4.0564338 10.8058262,4.393783 L7.02648971,9.71342659 L5.62452625,7.60511675 C5.39516713,7.26020042 4.92962491,7.1665228 4.58470858,7.39588191 C4.23979226,7.62524103 4.14611463,8.09078326 4.37547375,8.43569958 L6.37547375,11.4433526 Z" fill="#ffffff"></path>
            </g>
          </svg>

        {this.getLabel()}

    );
  }
}

ItemCheckbox.defaultProps = {
  handleChange: function () {}
};

ItemCheckbox.propTypes = {
  // Optional value for setting the checked state of the checkbox,
  // should be either true for 'checked' or false 'unchecked'
  checked: React.PropTypes.bool,
  // Optional value for setting disabled state
  disabled: React.PropTypes.bool,
  // Optional. Which field property is currently being edited
  // (usually passed down from form definition)
  editing: React.PropTypes.string,
  // Function to handle change event
  // (usually passed down from FieldCheckbox)
  handleChange: React.PropTypes.func,
  // Optional value for setting the indeterminate state of the checkbox,
  // should be either true or false
  indeterminate: React.PropTypes.bool,
  // Optional label for field
  label: React.PropTypes.string,
  // name of the field property
  // (usually passed down from form definition)
  name: React.PropTypes.string.isRequired,

  // Classes
  labelClass: React.PropTypes.string
};

module.exports = ItemCheckbox;
<commit_msg>Mute checkbox text for disabled checkboxes.<commit_after>import classNames from 'classnames';
import React from 'react';
import ReactDOM from 'react-dom';

import BindMixin from '../Mixin/BindMixin';
import Util from '../Util/Util';

class ItemCheckbox extends Util.mixin(BindMixin) {
  get methodsToBind() {
    return ['handleChange'];
  }

  componentDidMount() {
    super.componentDidMount(...arguments);
    this.updateCheckbox();
  }

  componentDidUpdate() {
    super.componentDidUpdate(...arguments);
    this.updateCheckbox();
  }

  updateCheckbox() {
    let {props, refs} = this;
    let checkbox = ReactDOM.findDOMNode(refs.checkbox);

    if (props.checked != null) {
      checkbox.checked = props.checked;
    }

    let indeterminate = props.indeterminate;
    if (indeterminate != null) {
      checkbox.indeterminate = indeterminate;
    }
  }

  handleChange(event) {
    this.props.handleEvent(
      'change',
      this.props.name,
      {
        checked: event.target.checked,
        indeterminate: event.target.indeterminate
      },
      event
    );
  }

  getLabel() {
    let label = this.props.label;
    if (!label) {
      return null;
    }

    return (

        {label}

    );
  }

  render() {
    let {props} = this;

    let labelClass = classNames({
      'form-row-element form-element-checkbox': true,
      'mute': props.disabled,
      [props.labelClass]: true
    });

    return (

        <input
          onChange={this.handleChange}
          disabled={props.disabled}
          ref="checkbox"
          type="checkbox" />

          <svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
            <g className="icon icon-svg-checkbox-indeterminate">
              <path d="M5,9.75 L11,9.75 C11.4142136,9.75 11.75,9.41421356 11.75,9 C11.75,8.58578644 11.4142136,8.25 11,8.25 L5,8.25 C4.58578644,8.25 4.25,8.58578644 4.25,9 C4.25,9.41421356 4.58578644,9.75 5,9.75 L5,9.75 Z" fill="#000000" fillOpacity="0.13"></path>
              <path d="M5,8.75 L11,8.75 C11.4142136,8.75 11.75,8.41421356 11.75,8 C11.75,7.58578644 11.4142136,7.25 11,7.25 L5,7.25 C4.58578644,7.25 4.25,7.58578644 4.25,8 C4.25,8.41421356 4.58578644,8.75 5,8.75 L5,8.75 Z" fill="#ffffff"></path>
            </g>
            <g className="icon icon-svg-checkbox-checked">
              <path d="M6.37547375,12.4433526 C6.66651906,12.8810343 7.30583183,12.8913338 7.61082475,12.4632544 L12.0274757,6.26416941 C12.2678262,5.92682021 12.1891933,5.45850202 11.8518441,5.21815145 C11.5144949,4.97780088 11.0461767,5.0564338 10.8058262,5.393783 L7.02648971,10.7134266 L5.62452625,8.60511675 C5.39516713,8.26020042 4.92962491,8.1665228 4.58470858,8.39588191 C4.23979226,8.62524103 4.14611463,9.09078326 4.37547375,9.43569958 L6.37547375,12.4433526 Z" fill="#000000" fillOpacity="0.13"></path>
              <path d="M6.37547375,11.4433526 C6.66651906,11.8810343 7.30583183,11.8913338 7.61082475,11.4632544 L12.0274757,5.26416941 C12.2678262,4.92682021 12.1891933,4.45850202 11.8518441,4.21815145 C11.5144949,3.97780088 11.0461767,4.0564338 10.8058262,4.393783 L7.02648971,9.71342659 L5.62452625,7.60511675 C5.39516713,7.26020042 4.92962491,7.1665228 4.58470858,7.39588191 C4.23979226,7.62524103 4.14611463,8.09078326 4.37547375,8.43569958 L6.37547375,11.4433526 Z" fill="#ffffff"></path>
            </g>
          </svg>

        {this.getLabel()}

    );
  }
}

ItemCheckbox.defaultProps = {
  handleChange: function () {}
};

ItemCheckbox.propTypes = {
  // Optional value for setting the checked state of the checkbox,
  // should be either true for 'checked' or false 'unchecked'
  checked: React.PropTypes.bool,
  // Optional value for setting disabled state
  disabled: React.PropTypes.bool,
  // Optional. Which field property is currently being edited
  // (usually passed down from form definition)
  editing: React.PropTypes.string,
  // Function to handle change event
  // (usually passed down from FieldCheckbox)
  handleChange: React.PropTypes.func,
  // Optional value for setting the indeterminate state of the checkbox,
  // should be either true or false
  indeterminate: React.PropTypes.bool,
  // Optional label for field
  label: React.PropTypes.string,
  // name of the field property
  // (usually passed down from form definition)
  name: React.PropTypes.string.isRequired,

  // Classes
  labelClass: React.PropTypes.string
};

module.exports = ItemCheckbox;
<|endoftext|>


<commit_before>var VAR = 0, TEXT = 1, OPEN = 2, CLOSE = 3, ATTR = 4
var ATTR_KEY = 5, ATTR_KEY_W = 6
var ATTR_VALUE_W = 7, ATTR_VALUE = 8
var ATTR_VALUE_SQ = 9, ATTR_VALUE_DQ = 10

module.exports = function (h, opts) {
  if (!opts) opts = {}
  var concat = opts.concat || function (a, b) {
    return String(a) + String(b)
  }

  return function (strings) {
    var state = TEXT, reg = ''
    var arglen = arguments.length
    var parts = []

    for (var i = 0; i < strings.length; i++) {
      if (i < arglen - 1) {
        var arg = arguments[i+1]
        var p = parse(strings[i])
        var xstate = state
        if (xstate === ATTR_VALUE_DQ) xstate = ATTR_VALUE
        if (xstate === ATTR_VALUE_SQ) xstate = ATTR_VALUE
        if (xstate === ATTR_VALUE_W) xstate = ATTR_VALUE
        if (xstate === ATTR) xstate = ATTR_KEY
        p.push([ VAR, xstate, arg ])
        parts.push.apply(parts, p)
      } else parts.push.apply(parts, parse(strings[i]))
    }

    var tree = [null,{},[]]
    var stack = [[tree,-1]]
    for (var i = 0; i < parts.length; i++) {
      var cur = stack[stack.length-1][0]
      var p = parts[i], s = p[0]
      if (s === OPEN && /^\//.test(p[1])) {
        var ix = stack[stack.length-1][1]
        if (stack.length > 1) {
          stack.pop()
          stack[stack.length-1][0][2][ix] = h(
            cur[0], cur[1], cur[2].length ? cur[2] : undefined
          )
        }
      } else if (s === OPEN) {
        var c = [p[1],{},[]]
        cur[2].push(c)
        stack.push([c,cur[2].length-1])
      } else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) {
        var key = ''
        var copyKey
        for (; i < parts.length; i++) {
          if (parts[i][0] === ATTR_KEY) {
            key = concat(key, parts[i][1])
          } else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) {
            if (typeof parts[i][2] === 'object' && !key) {
              for(copyKey in parts[i][2]) {
                if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) {
                  cur[1][copyKey] = parts[i][2][copyKey]
                }
              }
            } else {
              key = concat(key, parts[i][2])
            }
          } else break
        }
        for (; i < parts.length; i++) {
          if (parts[i][0] === ATTR_VALUE) {
            if (!cur[1][key]) cur[1][key] = strfn(parts[i][1])
            else cur[1][key] = concat(cur[1][key], parts[i][1])
          } else if (parts[i][0] === VAR && parts[i][1] === ATTR_VALUE) {
            if (!cur[1][key]) cur[1][key] = strfn(parts[i][2])
            else cur[1][key] = concat(cur[1][key], parts[i][2])
          } else {
            i--
            break
          }
        }
      } else if (s === ATTR_KEY) {
        cur[1][p[1]] = true
      } else if (s === VAR && p[1] === ATTR_KEY) {
        cur[1][p[2]] = true
      } else if (s === CLOSE) {
        if (selfClosing(cur[0]) && stack.length) {
          var ix = stack[stack.length-1][1]
          stack.pop()
          stack[stack.length-1][0][2][ix] = h(
            cur[0], cur[1], cur[2].length ? cur[2] : undefined
          )
        }
      } else if (s === VAR && p[1] === TEXT) {
        if (p[2] === undefined || p[2] === null) p[2] = ''
        else if (!p[2]) p[2] = concat('', p[2])
        if (Array.isArray(p[2][0])) {
          cur[2].push.apply(cur[2], p[2])
        } else {
          cur[2].push(p[2])
        }
      } else if (s === TEXT) {
        cur[2].push(p[1])
      } else {
        throw new Error('unhandled: ' + s)
      }
    }

    if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) {
      tree[2].shift()
    }

    if (tree[2].length > 2
    || (tree[2].length === 2 && /\S/.test(tree[2][1]))) {
      throw new Error(
        'multiple root elements must be wrapped in an enclosing tag'
      )
    }
    return tree[2][0]

    function parse (str) {
      var res = []
      if (state === ATTR_VALUE_W) state = ATTR
      for (var i = 0; i < str.length; i++) {
        var c = str.charAt(i)
        if (state === TEXT && c === '<') {
          if (reg.length) res.push([TEXT, reg])
          reg = ''
          state = OPEN
        } else if (c === '>' && !quot(state)) {
          if (state === OPEN) {
            res.push([OPEN,reg])
          } else if (state === ATTR_KEY) {
            res.push([ATTR_KEY,reg])
          } else if (state === ATTR_VALUE && reg.length) {
            res.push([ATTR_VALUE,reg])
          }
          res.push([CLOSE])
          reg = ''
          state = TEXT
        } else if (state === TEXT) {
          reg += c
        } else if (state === OPEN && /\s/.test(c)) {
          res.push([OPEN, reg])
          reg = ''
          state = ATTR
        } else if (state === OPEN) {
          reg += c
        } else if (state === ATTR && /[\w-]/.test(c)) {
          state = ATTR_KEY
          reg = c
        } else if (state === ATTR_KEY && /\s/.test(c)) {
          res.push([ATTR_KEY,reg])
          reg = ''
          state = ATTR_KEY_W
        } else if (state === ATTR_KEY && c === '=') {
          res.push([ATTR_KEY,reg])
          reg = ''
          state = ATTR_VALUE_W
        } else if (state === ATTR_KEY) {
          reg += c
        } else if (state === ATTR_KEY_W && c === '=') {
          state = ATTR_VALUE_W
        } else if (state === ATTR_KEY_W && !/\s/.test(c)) {
          state = ATTR
          i--
        } else if (state === ATTR_VALUE_W && c === '"') {
          state = ATTR_VALUE_DQ
        } else if (state === ATTR_VALUE_W && c === "'") {
          state = ATTR_VALUE_SQ
        } else if (state === ATTR_VALUE_DQ && c === '"') {
          res.push([ATTR_VALUE,reg])
          reg = ''
          state = ATTR
        } else if (state === ATTR_VALUE_SQ && c === "'") {
          res.push([ATTR_VALUE,reg])
          reg = ''
          state = ATTR
        } else if (state === ATTR_VALUE_W && !/\s/.test(c)) {
          state = ATTR_VALUE
          i--
        } else if (state === ATTR_VALUE && /\s/.test(c)) {
          res.push([ATTR_VALUE,reg])
          reg = ''
          state = ATTR
        } else if (state === ATTR_VALUE || state === ATTR_VALUE_SQ
        || state === ATTR_VALUE_DQ) {
          reg += c
        }
      }
      if (state === TEXT && reg.length) {
        res.push([TEXT,reg])
        reg = ''
      } else if (state === ATTR_VALUE && reg.length) {
        res.push([ATTR_VALUE,reg])
        reg = ''
      } else if (state === ATTR_VALUE_DQ && reg.length) {
        res.push([ATTR_VALUE,reg])
        reg = ''
      } else if (state === ATTR_VALUE_SQ && reg.length) {
        res.push([ATTR_VALUE,reg])
        reg = ''
      } else if (state === ATTR_KEY) {
        res.push([ATTR_KEY,reg])
        reg = ''
      }
      return res
    }
  }

  function strfn (x) {
    if (typeof x === 'function') return x
    else if (typeof x === 'string') return x
    else if (x && typeof x === 'object') return x
    else return concat('', x)
  }
}

function quot (state) {
  return state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ
}

var hasOwn = Object.prototype.hasOwnProperty
function has (obj, key) { return hasOwn.call(obj, key) }

var closeRE = RegExp('^(' + [
  'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed',
  'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param',
  'source', 'track', 'wbr',
  // SVG TAGS
  'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor',
  'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile',
  'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix',
  'feComponentTransfer', 'feComposite','feConvolveMatrix', 'feDiffuseLighting',
  'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB',
  'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode',
  'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting',
  'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'font', 'font-face',
  'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri',
  'foreignObject', 'glyph', 'glyphRef', 'hkern', 'image', 'line',
  'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph', 'mpath',
  'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect',
  'set', 'stop', 'switch', 'symbol', 'text', 'textPath', 'title', 'tref',
  'tspan', 'use', 'view', 'vkern'
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$')
function selfClosing (tag) { return closeRE.test(tag) }
<commit_msg>remove title and text from self-closing list<commit_after>var VAR = 0, TEXT = 1, OPEN = 2, CLOSE = 3, ATTR = 4
var ATTR_KEY = 5, ATTR_KEY_W = 6
var ATTR_VALUE_W = 7, ATTR_VALUE = 8
var ATTR_VALUE_SQ = 9, ATTR_VALUE_DQ = 10

module.exports = function (h, opts) {
  if (!opts) opts = {}
  var concat = opts.concat || function (a, b) {
    return String(a) + String(b)
  }

  return function (strings) {
    var state = TEXT, reg = ''
    var arglen = arguments.length
    var parts = []

    for (var i = 0; i < strings.length; i++) {
      if (i < arglen - 1) {
        var arg = arguments[i+1]
        var p = parse(strings[i])
        var xstate = state
        if (xstate === ATTR_VALUE_DQ) xstate = ATTR_VALUE
        if (xstate === ATTR_VALUE_SQ) xstate = ATTR_VALUE
        if (xstate === ATTR_VALUE_W) xstate = ATTR_VALUE
        if (xstate === ATTR) xstate = ATTR_KEY
        p.push([ VAR, xstate, arg ])
        parts.push.apply(parts, p)
      } else parts.push.apply(parts, parse(strings[i]))
    }

    var tree = [null,{},[]]
    var stack = [[tree,-1]]
    for (var i = 0; i < parts.length; i++) {
      var cur = stack[stack.length-1][0]
      var p = parts[i], s = p[0]
      if (s === OPEN && /^\//.test(p[1])) {
        var ix = stack[stack.length-1][1]
        if (stack.length > 1) {
          stack.pop()
          stack[stack.length-1][0][2][ix] = h(
            cur[0], cur[1], cur[2].length ? cur[2] : undefined
          )
        }
      } else if (s === OPEN) {
        var c = [p[1],{},[]]
        cur[2].push(c)
        stack.push([c,cur[2].length-1])
      } else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) {
        var key = ''
        var copyKey
        for (; i < parts.length; i++) {
          if (parts[i][0] === ATTR_KEY) {
            key = concat(key, parts[i][1])
          } else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) {
            if (typeof parts[i][2] === 'object' && !key) {
              for(copyKey in parts[i][2]) {
                if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) {
                  cur[1][copyKey] = parts[i][2][copyKey]
                }
              }
            } else {
              key = concat(key, parts[i][2])
            }
          } else break
        }
        for (; i < parts.length; i++) {
          if (parts[i][0] === ATTR_VALUE) {
            if (!cur[1][key]) cur[1][key] = strfn(parts[i][1])
            else cur[1][key] = concat(cur[1][key], parts[i][1])
          } else if (parts[i][0] === VAR && parts[i][1] === ATTR_VALUE) {
            if (!cur[1][key]) cur[1][key] = strfn(parts[i][2])
            else cur[1][key] = concat(cur[1][key], parts[i][2])
          } else {
            i--
            break
          }
        }
      } else if (s === ATTR_KEY) {
        cur[1][p[1]] = true
      } else if (s === VAR && p[1] === ATTR_KEY) {
        cur[1][p[2]] = true
      } else if (s === CLOSE) {
        if (selfClosing(cur[0]) && stack.length) {
          var ix = stack[stack.length-1][1]
          stack.pop()
          stack[stack.length-1][0][2][ix] = h(
            cur[0], cur[1], cur[2].length ? cur[2] : undefined
          )
        }
      } else if (s === VAR && p[1] === TEXT) {
        if (p[2] === undefined || p[2] === null) p[2] = ''
        else if (!p[2]) p[2] = concat('', p[2])
        if (Array.isArray(p[2][0])) {
          cur[2].push.apply(cur[2], p[2])
        } else {
          cur[2].push(p[2])
        }
      } else if (s === TEXT) {
        cur[2].push(p[1])
      } else {
        throw new Error('unhandled: ' + s)
      }
    }

    if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) {
      tree[2].shift()
    }

    if (tree[2].length > 2
    || (tree[2].length === 2 && /\S/.test(tree[2][1]))) {
      throw new Error(
        'multiple root elements must be wrapped in an enclosing tag'
      )
    }
    return tree[2][0]

    function parse (str) {
      var res = []
      if (state === ATTR_VALUE_W) state = ATTR
      for (var i = 0; i < str.length; i++) {
        var c = str.charAt(i)
        if (state === TEXT && c === '<') {
          if (reg.length) res.push([TEXT, reg])
          reg = ''
          state = OPEN
        } else if (c === '>' && !quot(state)) {
          if (state === OPEN) {
            res.push([OPEN,reg])
          } else if (state === ATTR_KEY) {
            res.push([ATTR_KEY,reg])
          } else if (state === ATTR_VALUE && reg.length) {
            res.push([ATTR_VALUE,reg])
          }
          res.push([CLOSE])
          reg = ''
          state = TEXT
        } else if (state === TEXT) {
          reg += c
        } else if (state === OPEN && /\s/.test(c)) {
          res.push([OPEN, reg])
          reg = ''
          state = ATTR
        } else if (state === OPEN) {
          reg += c
        } else if (state === ATTR && /[\w-]/.test(c)) {
          state = ATTR_KEY
          reg = c
        } else if (state === ATTR_KEY && /\s/.test(c)) {
          res.push([ATTR_KEY,reg])
          reg = ''
          state = ATTR_KEY_W
        } else if (state === ATTR_KEY && c === '=') {
          res.push([ATTR_KEY,reg])
          reg = ''
          state = ATTR_VALUE_W
        } else if (state === ATTR_KEY) {
          reg += c
        } else if (state === ATTR_KEY_W && c === '=') {
          state = ATTR_VALUE_W
        } else if (state === ATTR_KEY_W && !/\s/.test(c)) {
          state = ATTR
          i--
        } else if (state === ATTR_VALUE_W && c === '"') {
          state = ATTR_VALUE_DQ
        } else if (state === ATTR_VALUE_W && c === "'") {
          state = ATTR_VALUE_SQ
        } else if (state === ATTR_VALUE_DQ && c === '"') {
          res.push([ATTR_VALUE,reg])
          reg = ''
          state = ATTR
        } else if (state === ATTR_VALUE_SQ && c === "'") {
          res.push([ATTR_VALUE,reg])
          reg = ''
          state = ATTR
        } else if (state === ATTR_VALUE_W && !/\s/.test(c)) {
          state = ATTR_VALUE
          i--
        } else if (state === ATTR_VALUE && /\s/.test(c)) {
          res.push([ATTR_VALUE,reg])
          reg = ''
          state = ATTR
        } else if (state === ATTR_VALUE || state === ATTR_VALUE_SQ
        || state === ATTR_VALUE_DQ) {
          reg += c
        }
      }
      if (state === TEXT && reg.length) {
        res.push([TEXT,reg])
        reg = ''
      } else if (state === ATTR_VALUE && reg.length) {
        res.push([ATTR_VALUE,reg])
        reg = ''
      } else if (state === ATTR_VALUE_DQ && reg.length) {
        res.push([ATTR_VALUE,reg])
        reg = ''
      } else if (state === ATTR_VALUE_SQ && reg.length) {
        res.push([ATTR_VALUE,reg])
        reg = ''
      } else if (state === ATTR_KEY) {
        res.push([ATTR_KEY,reg])
        reg = ''
      }
      return res
    }
  }

  function strfn (x) {
    if (typeof x === 'function') return x
    else if (typeof x === 'string') return x
    else if (x && typeof x === 'object') return x
    else return concat('', x)
  }
}

function quot (state) {
  return state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ
}

var hasOwn = Object.prototype.hasOwnProperty
function has (obj, key) { return hasOwn.call(obj, key) }

var closeRE = RegExp('^(' + [
  'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed',
  'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param',
  'source', 'track', 'wbr',
  // SVG TAGS
  'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor',
  'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile',
  'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix',
  'feComponentTransfer', 'feComposite','feConvolveMatrix', 'feDiffuseLighting',
  'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB',
  'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode',
  'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting',
  'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'font', 'font-face',
  'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri',
  'foreignObject', 'glyph', 'glyphRef', 'hkern', 'image', 'line',
  'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph', 'mpath',
  'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect',
  'set', 'stop', 'switch', 'symbol', 'textPath', 'tref',
  'tspan', 'use', 'view', 'vkern'
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$')
function selfClosing (tag) { return closeRE.test(tag) }
<|endoftext|>


<commit_before>UIAElementArray.prototype.type = function() {
	return "UIAElementArray";
}

UIAElementArray.prototype.reference = function() {
	if (!this.id) {
		UIAutomation.cache.store(this);
	}
	return this.id;
}
/**
 * returns the class for the element, as per
 * http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef
 */
UIAElement.prototype.type = function() {
	return this.toString().replace('[object ', '').replace(']', '');
}

UIAElement.prototype.tap2 = function() {
	if (this.isVisible()) {
		var rect = this.rect();
		var x = rect.origin.x + (rect.size.width / 2);
		var y = rect.origin.y + (rect.size.height / 2);
		var point = {
			'x' : x,
			'y' : y
		};
		UIATarget.localTarget().tap(point);
	} else {
		var ex = new UIAutomationException("element is not visible", 11);
		throw ex;
	}

}

UIAElement.prototype.reference = function() {
	if (!this.id) {
		UIAutomation.cache.store(this);
	}
	return this.id;
}

/**
 * can't find a way to detect stale object. CheckIsValid doesn't do it properly.
 * Trying to scroll to the element seems like a valid approximation.
 */
UIAElement.prototype.isStale = function() {
	if (this.checkIsValid() == false) {
		return true;
	} else {
		try {
			this.scrollToVisible();
			return false;
		} catch (err) {
			if (err.message
					&& err.message
							.indexOf('scrollToVisible cannot be used') != -1) {
				return true;
			}
		}
	}
	return false;
}

UIAElement.prototype.element = function(depth, criteria) {
	var all = this.getChildren(depth);
	var res = new Array();

	for ( var i = 0; i < all.length; i++) {
		var element = all[i];
		if (element.matches(criteria)) {
			return element;
		}
	}
	throw new UIAutomationException("cannot find element for criteria :"
			+ JSON.stringify(criteria), 7);
}

UIAElement.prototype.elements2 = function(depth, criteria) {
	var all = this.getChildren(depth);
	var res = new Array();
	if (criteria) {
		for ( var i = 0; i < all.length; i++) {
			var element = all[i];
			if (element.matches(criteria)) {
				res.push(element);
			}
		}
		return new MyUIAElementArray(res);
	} else {
		return new MyUIAElementArray(all);
	}
}

UIAElement.prototype.asNode = function() {
	try {
		return {
			"type" : this.type(),
			"name" : this.name(),
			"value" : this.value(),
			"label" : this.label(),
			"rect" : this.rect(),
			"ref" : this.reference()
		};
	} catch (err) {
		return "error : " + err;
	}
}

UIAElement.prototype.tree = function(path) {
	var buildNode = function(element) {
		var res = element.asNode();
		var children = element.elements();
		if (children.length > 0) {
			var array = new Array();
			for ( var i = 0; i < children.length; i++) {
				array.push(buildNode(children[i]));
			}
			res.children = array;
		}
		return res;
	}

	var res = buildNode(this);
	UIATarget.localTarget().captureScreenWithName('current');
	var result = {
		tree : res,
		path : path
	};
	return result;
}
/**
 * return an array with all the children of the element. Goes depth deep in the
 * tree. depth = -1 or undefined gets all elements.
 */
UIAElement.prototype.getChildren = function(depth) {
	var res = new Array();

	if (!depth) {
		depth = -1;
	}
	var getChildren = function(depth, element) {
		res.push(element);
		var d = depth - 1;
		if (d > 0 || d !== -1) {
			var children = element.elements();
			var size = children.length;
			for ( var i = 0; i < size; i++) {
				var child = children[i];
				getChildren(d, child);
			}
		}
	}
	getChildren(depth, this)
	return res;
}
var getKeys = function(obj) {
	var keys = [];
	for ( var key in obj) {
		keys.push(key);
	}
	return keys;
}

UIAElement.prototype.matches = function(criteria) {
	if (!criteria) {
		return true;
	}
	// criteria only have one field.It's either :
	// AND + array of criterias
	// OR + array of criterias
	// NOT + criteria
	// criteria
	var keys = getKeys(criteria);

	// empty filder matches all.
	if (keys == 0) {
		return true;
	}

	if (keys.length == 1) {
		var key = keys[0];
		if (key === "AND") {
			var array = criteria[key];
			for ( var c in array) {
				if (!this.matches(array[c])) {
					return false;
				}
			}
			return true;
		} else if (key === "OR") {
			var array = criteria[key];
			for ( var c in array) {
				if (this.matches(array[c])) {
					return true;
				}
			}
			return false;
		} else if (key === "NOT") {
			return !this.matches(criteria[key]);
		} else {
			var current = this[key]();
			var expected = criteria[key];
			return current == expected;
		}
	} else {
		UIALogger.logMessage("not a valid criteria " + keys.length + " , ->"
				+ JSON.stringify(criteria));
	}
}
/**
 * create something similar to UIAelement array from a list of elements
 *
 * @param elements
 *            an array of native UIAElements.
 */
function MyUIAElementArray(elements) {
	this.elements = elements;
	this.length = elements.length;

	this.toArray = function() {
		return this.elements;
	}

	this.type = function() {
		return "UIAElementArray";
	}
	this.toString = function() {
		return "[object MyUIAElementArray]";
	}

	this.firstWithName = function(name) {
		for (i = 0; i < this.elements.length; i++) {
			var current = elements[i];
			log("element with name : " + current.name());
			if (current.name() === name) {
				return current;
			}
		}
		throw new UIAutomationException("cannot find an element with name="
				+ name);
	}

	this.buttons = function() {
		return this._getElementsOfType("UIAButton");
	}
	this.links = function() {
		return this._getElementsOfType("UIALink");
	}

	this.images = function() {
		return this._getElementsOfType("UIAImage");

	}

	this._getElementsOfType = function(type) {
		if (type) {
			var res = new Array();
			for (i = 0; i < this.all.length; i++) {
				var current = this.all[i];
				if (current.type() === type) {
					res.push(current);
				}
			}
			return res;
		} else {
			throw new UIAutomationException("param type missing");
		}

	}

	this.reference = function() {
		if (!this.id) {
			UIAutomation.cache.store(this);
		}
		return this.id;
	}

}
<commit_msg>adding findElement(s) implementation on arrays.<commit_after>UIAElementArray.prototype.type = function() {
	return "UIAElementArray";
}

UIAElementArray.prototype.reference = function() {
	if (!this.id) {
		UIAutomation.cache.store(this);
	}
	return this.id;
}

UIAElementArray.prototype.elements2 = function(depth,criteria) {
	log("elements2");
	var all = this.toArray();
	var res = new Array();
	for (var i=0;i<all.length;i++){
		var element = all[i];
		log("working on "+element)
		if (element.matches(criteria)) {
			res.push(element);
		}
	}
	return new MyUIAElementArray(res);
}

UIAElementArray.prototype.element = function(depth,criteria) {
	log("element");
	var all = this.toArray();
	for (var i=0;i<all.length;i++){
		var element = all[i];
		log("working on "+element)
		if (element.matches(criteria)) {
			log("about to return "+element)
			return element;
		}
	}
	throw new UIAutomationException("cannot find element for criteria :"
			+ JSON.stringify(criteria), 7);
}

/**
 * returns the class for the element, as per
 * http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef
 */
UIAElement.prototype.type = function() {
	return this.toString().replace('[object ', '').replace(']', '');
}

UIAElement.prototype.tap2 = function() {
	if (this.isVisible()) {
		var rect = this.rect();
		var x = rect.origin.x + (rect.size.width / 2);
		var y = rect.origin.y + (rect.size.height / 2);
		var point = {
			'x' : x,
			'y' : y
		};
		UIATarget.localTarget().tap(point);
	} else {
		var ex = new UIAutomationException("element is not visible", 11);
		throw ex;
	}

}

UIAElement.prototype.reference = function() {
	if (!this.id) {
		UIAutomation.cache.store(this);
	}
	return this.id;
}

/**
 * can't find a way to detect stale object. CheckIsValid doesn't do it properly.
 * Trying to scroll to the element seems like a valid approximation.
 */
UIAElement.prototype.isStale = function() {
	if (this.checkIsValid() == false) {
		return true;
	} else {
		try {
			this.scrollToVisible();
			return false;
		} catch (err) {
			if (err.message
					&& err.message
							.indexOf('scrollToVisible cannot be used') != -1) {
				return true;
			}
		}
	}
	return false;
}

UIAElement.prototype.element = function(depth, criteria) {
	var all = this.getChildren(depth);
	var res = new Array();

	for ( var i = 0; i < all.length; i++) {
		var element = all[i];
		if (element.matches(criteria)) {
			return element;
		}
	}
	throw new UIAutomationException("cannot find element for criteria :"
			+ JSON.stringify(criteria), 7);
}

UIAElement.prototype.elements2 = function(depth, criteria) {
	var all = this.getChildren(depth);
	var res = new Array();
	if (criteria) {
		for ( var i = 0; i < all.length; i++) {
			var element = all[i];
			if (element.matches(criteria)) {
				res.push(element);
			}
		}
		return new MyUIAElementArray(res);
	} else {
		return new MyUIAElementArray(all);
	}
}

UIAElement.prototype.asNode = function() {
	try {
		return {
			"type" : this.type(),
			"name" : this.name(),
			"value" : this.value(),
			"label" : this.label(),
			"rect" : this.rect(),
			"ref" : this.reference()
		};
	} catch (err) {
		return "error : " + err;
	}
}

UIAElement.prototype.tree = function(path) {
	var buildNode = function(element) {
		var res = element.asNode();
		var children = element.elements();
		if (children.length > 0) {
			var array = new Array();
			for ( var i = 0; i < children.length; i++) {
				array.push(buildNode(children[i]));
			}
			res.children = array;
		}
		return res;
	}

	var res = buildNode(this);
	UIATarget.localTarget().captureScreenWithName('current');
	var result = {
		tree : res,
		path : path
	};
	return result;
}
/**
 * return an array with all the children of the element. Goes depth deep in the
 * tree. depth = -1 or undefined gets all elements.
 */
UIAElement.prototype.getChildren = function(depth) {
	var res = new Array();

	if (!depth) {
		depth = -1;
	}
	var getChildren = function(depth, element) {
		res.push(element);
		var d = depth - 1;
		if (d > 0 || d !== -1) {
			var children = element.elements();
			var size = children.length;
			for ( var i = 0; i < size; i++) {
				var child = children[i];
				getChildren(d, child);
			}
		}
	}
	getChildren(depth, this)
	return res;
}
var getKeys = function(obj) {
	var keys = [];
	for ( var key in obj) {
		keys.push(key);
	}
	return keys;
}

UIAElement.prototype.matches = function(criteria) {
	if (!criteria) {
		return true;
	}
	// criteria only have one field.It's either :
	// AND + array of criterias
	// OR + array of criterias
	// NOT + criteria
	// criteria
	var keys = getKeys(criteria);

	// empty filder matches all.
	if (keys == 0) {
		return true;
	}

	if (keys.length == 1) {
		var key = keys[0];
		if (key === "AND") {
			var array = criteria[key];
			for ( var c in array) {
				if (!this.matches(array[c])) {
					return false;
				}
			}
			return true;
		} else if (key === "OR") {
			var array = criteria[key];
			for ( var c in array) {
				if (this.matches(array[c])) {
					return true;
				}
			}
			return false;
		} else if (key === "NOT") {
			return !this.matches(criteria[key]);
		} else {
			var current = this[key]();
			var expected = criteria[key];
			return current == expected;
		}
	} else {
		UIALogger.logMessage("not a valid criteria " + keys.length + " , ->"
				+ JSON.stringify(criteria));
	}
}
/**
 * create something similar to UIAelement array from a list of elements
 *
 * @param elements
 *            an array of native UIAElements.
 */
function MyUIAElementArray(elements) {
	this.elements = elements;
	this.length = elements.length;

	this.toArray = function() {
		return this.elements;
	}

	this.type = function() {
		return "UIAElementArray";
	}
	this.toString = function() {
		return "[object MyUIAElementArray]";
	}

	this.firstWithName = function(name) {
		for (i = 0; i < this.elements.length; i++) {
			var current = elements[i];
			log("element with name : " + current.name());
			if (current.name() === name) {
				return current;
			}
		}
		throw new UIAutomationException("cannot find an element with name="
				+ name);
	}

	this.buttons = function() {
		return this._getElementsOfType("UIAButton");
	}
	this.links = function() {
		return this._getElementsOfType("UIALink");
	}

	this.images = function() {
		return this._getElementsOfType("UIAImage");

	}

	this._getElementsOfType = function(type) {
		if (type) {
			var res = new Array();
			for (i = 0; i < this.all.length; i++) {
				var current = this.all[i];
				if (current.type() === type) {
					res.push(current);
				}
			}
			return res;
		} else {
			throw new UIAutomationException("param type missing");
		}

	}

	this.reference = function() {
		if (!this.id) {
			UIAutomation.cache.store(this);
		}
		return this.id;
	}

	this.element = UIAElementArray.prototype.element;
	this.elements2 = UIAElementArray.prototype.elements2;

}
<|endoftext|>


<commit_before>const React = require('react-native');

const {
  Dimensions,
  StyleSheet,
  Component,
  View
} = React;

const window = Dimensions.get('window');

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    width: window.width,
    height: window.height
  }
});

function purifyProps(props) {
  let newProps = { ...props };

  delete newProps.id;
  delete newProps.sceneDidMount;
  delete newProps.sceneWillUnmount;

  return newProps;
}

const sceneWrapper = (LoadingComponent) => {
  return (SceneComponent) =>
    class WrapComponent extends Component {
      constructor(props, context) {
        super(props, context);

        this.state = {
          isReady: !(!!LoadingComponent)
        };
      }

      componentDidMount() {
        const { isChild, sceneDidMount } = this.props;
        if (!isChild) {
          sceneDidMount(this, this.sceneReadyToRender.bind(this));
        }
      }

      componentWillUnmount() {
        const { isChild, sceneWillUnmount } = this.props;
        if (!isChild) {
          sceneWillUnmount(this);
        }
      }

      isSceneNeedLoading() {
        return !!LoadingComponent;
      }

      sceneReadyToRender() {
        if (this.isSceneNeedLoading() && !this.state.isReady) {
          this.setState({ isReady: true });
        }
      }

      willBlur() {
        const { scene } = this.refs;
        if (scene && scene.sceneWillBlur) {
          scene.sceneWillBlur();
        }
      }

      didBlur() {
        const { scene } = this.refs;
        if (scene && scene.sceneDidBlur) {
          scene.sceneDidBlur();
        }
      }

      willFocus() {
        const { scene } = this.refs;
        if (scene && scene.sceneWillFocus) {
          scene.sceneWillFocus();
        }
      }

      didFocus() {
        const { scene } = this.refs;
        if (scene && scene.sceneDidFocus) {
          scene.sceneDidFocus();
        }
      }

      render() {
        const { position } = this.props;
        const props = purifyProps(this.props);

        const renderedComponent = !this.state.isReady ?
                                    <LoadingComponent {...props}/> :
                                    <SceneComponent ref="scene" {...props}/>;

        const rootStyleOnly = position? { top: position.y, left: position.x } : {};

        return (
          <View ref="root" style={[styles.container, rootStyleOnly]}>
            {renderedComponent}
          </View>
        );
      }
    }
};

module.exports = sceneWrapper;
<commit_msg>cleaned up some code<commit_after>const React = require('react-native');

const {
  Dimensions,
  StyleSheet,
  Component,
  View
} = React;

const window = Dimensions.get('window');

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    width: window.width,
    height: window.height
  }
});

function purifyProps(props) {
  let newProps = { ...props };

  delete newProps.id;
  delete newProps.sceneDidMount;
  delete newProps.sceneWillUnmount;
  delete newProps.isChild;
  delete newProps.position;

  return newProps;
}

const sceneWrapper = (LoadingComponent) => {
  return (SceneComponent) =>
    class WrapComponent extends Component {
      constructor(props, context) {
        super(props, context);

        this.state = {
          isReady: !(!!LoadingComponent)
        };
      }

      componentDidMount() {
        const { isChild, sceneDidMount } = this.props;
        if (!isChild) {
          sceneDidMount(this, this.sceneReadyToRender.bind(this));
        }
      }

      componentWillUnmount() {
        const { isChild, sceneWillUnmount } = this.props;
        if (!isChild) {
          sceneWillUnmount(this);
        }
      }

      isSceneNeedLoading() {
        return !!LoadingComponent;
      }

      sceneReadyToRender() {
        if (this.isSceneNeedLoading() && !this.state.isReady) {
          this.setState({ isReady: true });
        }
      }

      willBlur() {
        const { scene } = this.refs;
        if (scene && scene.sceneWillBlur) {
          scene.sceneWillBlur();
        }
      }

      didBlur() {
        const { scene } = this.refs;
        if (scene && scene.sceneDidBlur) {
          scene.sceneDidBlur();
        }
      }

      willFocus() {
        const { scene } = this.refs;
        if (scene && scene.sceneWillFocus) {
          scene.sceneWillFocus();
        }
      }

      didFocus() {
        const { scene } = this.refs;
        if (scene && scene.sceneDidFocus) {
          scene.sceneDidFocus();
        }
      }

      render() {
        const { isChild, position } = this.props;
        const props = purifyProps(this.props);

        const renderedComponent = !this.state.isReady ?
                                    <LoadingComponent {...props}/> :
                                    <SceneComponent ref="scene" {...props}/>;

        const rootStyleOnly = isChild? {} : { top: position.y, left: position.x };

        return (
          <View ref="root" style={[styles.container, rootStyleOnly]}>
            {renderedComponent}
          </View>
        );
      }
    }
};

module.exports = sceneWrapper;
<|endoftext|>


<commit_before>var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var path = require('path');

module.exports = function walk (dir, opts, emitter, dstat) {
    if (!opts) opts = {};
    var fdir = opts._original || dir;
    opts._original = undefined;

    if (!emitter) {
        emitter = new EventEmitter;
        emitter._pending = 0;
        emitter._seen = {};
    }
    emitter._pending ++;
    emitter.on('end', function () {
        emitter._seen = null;
    });

    if (dstat) {
        var stopped = false;
        emitter.emit('directory', fdir, dstat, function stop () {
            stopped = true;
        });
        emitter.emit('path', fdir, dstat);
        if (!stopped) fs.readdir(dir, onreaddir);
        else check()
    }
    else fs.lstat(dir, function onstat (err, stat) {
        if (err) return emitter.emit('end');
        emitter._seen[stat.ino] = true;

        if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', fdir, stat);
            fs.readlink(dir, function (err, rfile) {
                if (err) return emitter.emit('end');
                var file_ = path.resolve(dir, rfile);
                emitter.emit('readlink', fdir, file_);
                fs.lstat(file_, onstat);
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', fdir, stat);
            emitter.emit('path', fdir, stat);
            emitter.emit('end');
        }
        else if (stat.isDirectory()) {
            var stopped = false;
            emitter.emit('directory', fdir, stat, function stop () {
                stopped = true;
            });
            emitter.emit('path', fdir, stat);
            if (!stopped) fs.readdir(dir, onreaddir);
            else check()
        }
        else {
            emitter.emit('file', fdir, stat);
            emitter.emit('path', fdir, stat);
            emitter.emit('end');
        }
    });

    return emitter;

    function check () {
        if (-- emitter._pending === 0) finish();
    }

    function finish () {
        emitter.emit('end');
    }

    function onreaddir (err, files) {
        emitter._pending --;
        if (err) return check();

        files.forEach(function (rfile) {
            emitter._pending ++;
            var file = path.join(fdir, rfile);

            fs.lstat(file, function (err, stat) {
                if (err) check()
                else onstat(file, stat)
            });
        });
    }

    function onstat (file, stat, original) {
        if (emitter._seen[stat.ino]) return check();
        emitter._seen[stat.ino] = true;

        if (stat.isDirectory()) {
            if (original) opts._original = original;
            walk(file, opts, emitter, stat);
            check();
        }
        else if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', file, stat);

            fs.readlink(file, function (err, rfile) {
                if (err) return check();
                var file_ = path.resolve(path.dirname(file), rfile);

                emitter.emit('readlink', file, file_);
                fs.lstat(file_, function (err, stat_) {
                    if (err) return check();

                    emitter._pending ++;
                    onstat(file_, stat_, file);
                    check();
                });
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
        else {
            emitter.emit('file', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
    }
};
<commit_msg>get rid of naggy listener warning<commit_after>var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var path = require('path');

module.exports = function walk (dir, opts, emitter, dstat) {
    if (!opts) opts = {};
    var fdir = opts._original || dir;
    opts._original = undefined;

    if (!emitter) {
        emitter = new EventEmitter;
        emitter.setMaxListeners(Infinity);
        emitter._pending = 0;
        emitter._seen = {};
    }
    emitter._pending ++;
    emitter.on('end', function () {
        emitter._seen = null;
    });

    if (dstat) {
        var stopped = false;
        emitter.emit('directory', fdir, dstat, function stop () {
            stopped = true;
        });
        emitter.emit('path', fdir, dstat);
        if (!stopped) fs.readdir(dir, onreaddir);
        else check()
    }
    else fs.lstat(dir, function onstat (err, stat) {
        if (err) return emitter.emit('end');
        emitter._seen[stat.ino] = true;

        if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', fdir, stat);
            fs.readlink(dir, function (err, rfile) {
                if (err) return emitter.emit('end');
                var file_ = path.resolve(dir, rfile);
                emitter.emit('readlink', fdir, file_);
                fs.lstat(file_, onstat);
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', fdir, stat);
            emitter.emit('path', fdir, stat);
            emitter.emit('end');
        }
        else if (stat.isDirectory()) {
            var stopped = false;
            emitter.emit('directory', fdir, stat, function stop () {
                stopped = true;
            });
            emitter.emit('path', fdir, stat);
            if (!stopped) fs.readdir(dir, onreaddir);
            else check()
        }
        else {
            emitter.emit('file', fdir, stat);
            emitter.emit('path', fdir, stat);
            emitter.emit('end');
        }
    });

    return emitter;

    function check () {
        if (-- emitter._pending === 0) finish();
    }

    function finish () {
        emitter.emit('end');
    }

    function onreaddir (err, files) {
        emitter._pending --;
        if (err) return check();

        files.forEach(function (rfile) {
            emitter._pending ++;
            var file = path.join(fdir, rfile);

            fs.lstat(file, function (err, stat) {
                if (err) check()
                else onstat(file, stat)
            });
        });
    }

    function onstat (file, stat, original) {
        if (emitter._seen[stat.ino]) return check();
        emitter._seen[stat.ino] = true;

        if (stat.isDirectory()) {
            if (original) opts._original = original;
            walk(file, opts, emitter, stat);
            check();
        }
        else if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', file, stat);

            fs.readlink(file, function (err, rfile) {
                if (err) return check();
                var file_ = path.resolve(path.dirname(file), rfile);

                emitter.emit('readlink', file, file_);
                fs.lstat(file_, function (err, stat_) {
                    if (err) return check();

                    emitter._pending ++;
                    onstat(file_, stat_, file);
                    check();
                });
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
        else {
            emitter.emit('file', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
    }
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs')
  , mkdirp = require('mkdirp')
  , path = require('path')
  , phonegap = require('phonegap')
  , program = require('commander')
  , remove = require('remove')
  , replace = require('replace')
  , request = require('request')
  , string = require('string');

program
  .version('0.0.1')
  .option('-C, --chdir <path>', 'change the working directory', String, '')
  .parse(process.argv);

cwd = path.resolve(__dirname, program.chdir);

if (!fs.existsSync(path.join(cwd, 'server.js'))) {
  return console.error('this is not a derby project');
}

program
  .command('init [dir]')
  .description('Initializes phonegap directory within an existing derby project.')
  .action(function (dir, options) {
    dir = path.join(cwd, dir || 'phonegap');
    var name = require(path.join(cwd, 'package.json')).name || '';
    var id = 'com.phonegap.' + string(name).dasherize(name).chompLeft('-');

    phonegap.create({id: id, name: name, path: dir}, function () {
      remove.removeSync(path.join(dir, 'www/css'));
      remove.removeSync(path.join(dir, 'www/img'));
      remove.removeSync(path.join(dir, 'www/index.html'));
      remove.removeSync(path.join(dir, 'www/js'));
      fs.mkdirSync(path.join(dir, 'www/derby'));
      mkdirp.sync(path.join(cwd, 'public/shared'));
      fs.symlinkSync(path.join(cwd, 'public/shared'), path.join(dir, 'www/shared'), 'dir');
    });
  });

program
  .command('build [dir]')
  .description('Builds phonegap application from a running derby server.')
  .option('-d, --domain <domain>', 'specify the domain [localhost]', String, 'localhost')
  .option('-p, --port <port>', 'specify the port [3000]', Number, 3000)
  .action(function (dir, options) {
    dir = path.join(cwd, dir || 'phonegap', 'www');
    var url = 'http://' + options.domain + ':' + options.port + '/';
    var file = path.join(dir, 'index.html');
    var appPath = 'derby/lib-app-index.js';
    var appFile = path.join(dir, appPath);

    request(url).pipe(fs.createWriteStream(file)).on('finish', function () {
      replace({paths: [file], regex: '/derby/', replacement: 'derby/'});
      fs.appendFile(file, '<script src="phonegap.js"></script>');
    });

    request(url + appPath).pipe(fs.createWriteStream(appFile)).on('finish', function () {
      replace({paths: [appFile], regex: '//www', replacement: 'http://www'})
      replace({paths: [appFile], regex: "'/channel'", replacement: "'" + url + "channel'"});
    });
  });

program.parse(process.argv);<commit_msg>add google and server to whitelist<commit_after>#!/usr/bin/env node

var fs = require('fs')
  , mkdirp = require('mkdirp')
  , path = require('path')
  , phonegap = require('phonegap')
  , program = require('commander')
  , remove = require('remove')
  , replace = require('replace')
  , request = require('request')
  , string = require('string');

program
  .version('0.0.1')
  .option('-C, --chdir <path>', 'change the working directory', String, '')
  .parse(process.argv);

cwd = path.resolve(__dirname, program.chdir);

if (!fs.existsSync(path.join(cwd, 'server.js'))) {
  return console.error('this is not a derby project');
}

program
  .command('init [dir]')
  .description('Initializes phonegap directory within an existing derby project.')
  .action(function (dir, options) {
    dir = path.join(cwd, dir || 'phonegap');
    var name = require(path.join(cwd, 'package.json')).name || '';
    var id = 'com.phonegap.' + string(name).dasherize(name).chompLeft('-');

    phonegap.create({id: id, name: name, path: dir}, function () {
      remove.removeSync(path.join(dir, 'www/css'));
      remove.removeSync(path.join(dir, 'www/img'));
      remove.removeSync(path.join(dir, 'www/index.html'));
      remove.removeSync(path.join(dir, 'www/js'));
      fs.mkdirSync(path.join(dir, 'www/derby'));
      mkdirp.sync(path.join(cwd, 'public/shared'));
      fs.symlinkSync(path.join(cwd, 'public/shared'), path.join(dir, 'www/shared'), 'dir');
      replace({paths: [path.join(dir, 'www/config.xml')], regex: '<access', replacement: '<access origin="http://www.google.com" />\n\t<access origin="http://localhost:3000" role="server" />\n\t<access'});
    });
  });

program
  .command('build [dir]')
  .description('Builds phonegap application from a running derby server.')
  .option('-d, --domain <domain>', 'specify the domain [localhost]', String, 'localhost')
  .option('-p, --port <port>', 'specify the port [3000]', Number, 3000)
  .action(function (dir, options) {
    dir = path.join(cwd, dir || 'phonegap', 'www');
    var url = 'http://' + options.domain + ':' + options.port + '/';
    var file = path.join(dir, 'index.html');
    var appPath = 'derby/lib-app-index.js';
    var appFile = path.join(dir, appPath);

    replace({
      paths: [path.join(dir, 'config.xml')],
      regex: '<access origin=".+" role="server" />',
      replacement: '<access origin="' + url + '" role="server" />'
    });

    request(url).pipe(fs.createWriteStream(file)).on('finish', function () {
      replace({paths: [file], regex: '/derby', replacement: 'derby'});
      replace({paths: [file], regex: '/shared', replacement: 'shared'});
      fs.appendFile(file, '<script src="phonegap.js"></script>');
    });

    request(url + appPath).pipe(fs.createWriteStream(appFile)).on('finish', function () {
      replace({paths: [appFile], regex: '//www', replacement: 'http://www'})
      replace({paths: [appFile], regex: "'/channel'", replacement: "'" + url + "channel'"});
    });
  });

program.parse(process.argv);<|endoftext|>


<commit_before>var through = require('through2')
var pumpify = require('pumpify')
var once = require('once')
var lexint = require('lexicographic-integer')
var mutex = require('level-mutex')
var byteStream = require('byte-stream')
var debug = require('debug')('level-dat')
var util = require('util')
var events = require('events')

var noop = function() {}

var TYPES = ['update', 'delete', 'create']

var WRITE_BUFFER_SIZE = 1024 * 1024 * 16
var SEP = '\xff'
var PREFIX = {
  change: 's',
  data: 'd',
  version:  'r',
  cur: 'c',
  meta: 'm'
}

var PREFIX_CHANGE = SEP+PREFIX.change+SEP
var PREFIX_DATA = SEP+PREFIX.data+SEP
var PREFIX_VERSION = SEP+PREFIX.version+SEP
var PREFIX_CUR = SEP+PREFIX.cur+SEP
var PREFIX_META = SEP+PREFIX.meta+SEP

var conflict = function(key, version) {
  var err =  new Error('Key conflict. A row with that key already exists and/or has a newer version.')
  err.key = key
  err.version = version
  err.status = 409
  err.conflict = true
  return err
}

var waiter = function(missing, cb) {
  var done = false
  return function(err) {
    if (done) return
    if (err) {
      done = true
      return cb(err)
    }
    if (--missing) return
    done = true
    cb()
  }
}

var deleted = function(cur) {
  return cur.length > 2 && cur[cur.length-2] === SEP && cur[cur.length-1] === '1'
}

var pack = function(n) {
  return lexint.pack(n, 'hex')
}

var unpack = function(n) {
  return lexint.unpack(n, 'hex')
}

var LevelDat = function(db, opts, onready) {
  if (!(this instanceof LevelDat)) return new LevelDat(db, opts, onready)
  if (typeof opts === 'function') return new LevelDat(db, null, onready)
  if (!opts) opts = {}

  var self = this

  this.db = db
  this.mutex = mutex(db)
  this.change = opts.change || -1
  this.defaults = opts

  this.mutex.peekLast({last:PREFIX_CHANGE+SEP}, function(err, key, value) {
    if (err && err.message !== 'range not found') return self.emit('error', err)

    self.change = value ? JSON.parse(value)[0] : 0
    debug('head change: %d', self.change)
    self.emit('ready', self)
  })

  if (onready) this.on('ready', onready)
}

util.inherits(LevelDat, events.EventEmitter)

LevelDat.prototype.createVersionStream = function(key, opts) {
  opts = this._mixin(opts)
  opts.start = PREFIX_DATA+key+SEP
  opts.end = PREFIX_DATA+key+SEP+SEP

  var stream = through.obj(function(data, enc, cb) {
    var vidx = data.key.lastIndexOf(SEP)

    data = {
      key: data.key.slice(PREFIX_DATA.length, vidx),
      version: unpack(data.key.slice(vidx+1)),
      value: data.value
    }

    debug('get version (key: %s, version: %d)', data.key, data.version)
    cb(null, data)
  })

  var rs = this.db.createReadStream(opts)

  return pumpify.obj(rs, stream)
}

LevelDat.prototype.valueStream =
LevelDat.prototype.createValueStream = function(opts) {
  opts = this._mixin(opts)
  opts.keys = false
  opts.values = true
  return this.createReadStream(opts)
}

LevelDat.prototype.keyStream =
LevelDat.prototype.createKeyStream = function(opts) {
  opts = this._mixin(opts)
  opts.keys = true
  opts.values = false
  return this.createReadStream(opts)
}

LevelDat.prototype.readStream =
LevelDat.prototype.createReadStream = function(opts) {
  opts = this._mixin(opts)

  var self = this
  var keys = opts.keys !== false
  var values = opts.values !== false

  var rs = self.db.createReadStream({
    start: PREFIX_CUR+(opts.start || ''),
    end: PREFIX_CUR+(opts.end || SEP)
  })

  var get = through.obj(function(data, enc, cb) {
    var val = data.value
    var key = data.key.slice(PREFIX_CUR.length)

    if (deleted(val)) return cb()

    var version = unpack(val)
    self.mutex.get(PREFIX_DATA+key+SEP+val, opts, function(err, data) {
      if (err) return cb(err)
      debug('get data.%s (version: %d)', key, version)

      if (values && !keys) return cb(null, data)
      if (keys && !values) return cb(null, key)

      cb(null, {
        key: key,
        version: version,
        value: data
      })
    })
  })

  return pumpify.obj(rs, get)
}

LevelDat.prototype.writeStream =
LevelDat.prototype.createWriteStream = function(opts) {
  this._assert()
  opts = this._mixin(opts)

  var self = this

  var buffer = byteStream({
    limit: WRITE_BUFFER_SIZE,
    time: 3000
  })

  var format = through.obj(function(data, enc, cb) {
    data.length = data.value ? data.value.length || 1 : 1
    cb(null, data)
  })

  var ws = through.obj(function(batch, enc, cb) {
    self.batch(batch, cb)
  })

  return pumpify.obj(format, buffer, ws)
}

LevelDat.prototype.createChangesWriteStream = function(opts) {
  this._assert()
  opts = this._mixin(opts)

  var self = this

  var buffer = byteStream({
    limit: WRITE_BUFFER_SIZE,
    time: 3000
  })

  var format = through.obj(function(data, enc, cb) {
    if (!data.value && data.type !== 'delete') return cb(new Error('data.value is required'))
    data.length = data.value ? data.value.length || 1 : 1
    cb(null, data)
  })

  var ws = through.obj(function(batch, enc, cb) {
    var wait = waiter(batch.length, cb)

    for (var i = 0; i < batch.length; i++) {
      var b = batch[i]
      var v = pack(b.version)

      debug('put change (change: %d, key: %s, version: %d, type: %s)', b.change, b.key, b.version, b.type)

      if (b.type === 'delete') {
        self.mutex.put(PREFIX_CHANGE+pack(b.change), JSON.stringify([b.change, b.key, b.version, 'delete']), noop)
        self.mutex.put(PREFIX_CUR+b.key, v+SEP+'1', wait)
      } else {
        self.mutex.put(PREFIX_CHANGE+pack(b.change), JSON.stringify([b.change, b.key, b.version, b.type]), noop)
        self.mutex.put(PREFIX_CUR+b.key, v, noop)
        self.mutex.put(PREFIX_DATA+b.key+SEP+v, b.value, opts, wait)
      }
    }
  })

  return pumpify.obj(format, buffer, ws)
}

LevelDat.prototype.createChangesReadStream = function(opts) {
  opts = this._mixin(opts)

  var self = this
  var addData = !!opts.data

  var rs = this.db.createReadStream({
    start: PREFIX_CHANGE+pack(opts.change || 0),
    end: PREFIX_CHANGE+SEP
  })

  var format = through.obj(function(data, enc, cb) {
    var value = JSON.parse(data.value)

    var data = {
      key: value[1],
      version: value[2],
      change: value[0],
      type: value[3]
    }

    debug('get change (change: %d, key: %s, version: %d, type: %s, data: %s)', data.change, data.key, data.version, data.type, addData)
    if (!addData || data.type === 'delete') return cb(null, data)

    self._get(data.key, opts, data.version, function(err, value) {
      if (err) return cb(err)
      data.value = value
      cb(null, data)
    })
  })

  return pumpify.obj(rs, format)
}

LevelDat.prototype.get = function(key, opts, cb, version) {
  if (typeof opts === 'function') return this.get(key, null, opts)
  opts = this._mixin(opts)

  if (!opts.version) this._getLatest(key, opts, cb)
  else this._get(key, opts, opts.version, cb)
}

LevelDat.prototype._getLatest = function(key, opts, cb) {
  opts = this._mixin(opts)

  var self = this
  this.mutex.get(PREFIX_CUR+key, function(err, cur) {
    if (err) return cb(err)
    if (deleted(cur)) return cb(new Error('Key was deleted'))

    self._get(key, opts, unpack(cur), cb)
  })
}

LevelDat.prototype._get = function(key, opts, version, cb) {
  opts = this._mixin(opts)
  version = +version

  this.mutex.get(PREFIX_DATA+key+SEP+pack(version), opts, function(err, val) {
    if (err) return cb(err)

    debug('get data.%s (version: %d)', key, version)
    cb(null, val, version)
  })
}

LevelDat.prototype.put = function(key, value, opts, cb) {
  this._assert()
  if (typeof opts === 'function') return this.put(key, value, null, opts)
  if (!cb) cb = noop
  opts = this._mixin(opts)

  this._put(key, value, opts, opts.version, cb)
}

LevelDat.prototype.batch = function(batch, opts, cb) {
  if (typeof opts === 'function') return this.batch(batch, null, opts)
  if (!cb) cb = noop
  opts = this._mixin(opts)

  if (!batch.length) return cb()
  var wait = waiter(batch.length, cb)

  for (var i = 0; i < batch.length; i++) {
    var b = batch[i]
    if (b.type === 'delete') this.del(b.key, wait)
    else this._put(b.key, b.value, opts, b.version || 0, wait)
  }
}

LevelDat.prototype._put = function(key, value, opts, version, cb) {
  this._assert()
  var autoVersion = !version
  if (!version) version = 1
  opts = this._mixin(opts)

  var self = this

  this.mutex.get(PREFIX_CUR+key, function(_, curV) {
    if (curV) curV = unpack(curV)
    if (curV) debug('put data.%s existing version exist (old-version: %d, new-version: %d)', key, curV, version)

    if (version === curV && autoVersion && !opts.force) return cb(conflict(key, version))
    if (version < curV && !opts.force) return cb(conflict(key, version))
    if (version === curV) version++

    var v = pack(+version)
    var change = ++self.change

    debug('put data.%s (version: %d)', key, version)
    self.mutex.put(PREFIX_CHANGE+pack(change), JSON.stringify([change, key, version, curV ? 'update' : 'create']), noop)
    self.mutex.put(PREFIX_CUR+key, v, noop)
    self.mutex.put(PREFIX_DATA+key+SEP+v, value, opts, cb)
  })
}

LevelDat.prototype.del =
LevelDat.prototype.delete = function(key, cb) {
  this._assert()
  if (!cb) cb = noop

  var self = this

  this.mutex.get(PREFIX_CUR+key, function(err, v) {
    if (err) return cb(err)

    var change = ++self.change
    var version = unpack(v)

    debug('del data.%s', key)
    self.mutex.put(PREFIX_CHANGE+pack(change), JSON.stringify([change, key, version, 'delete']), noop)
    self.mutex.put(PREFIX_CUR+key, v+SEP+'1', cb)
  })
}

LevelDat.prototype._mixin = function(opts) {
  if (!opts) opts = {}
  if (!opts.valueEncoding) opts.valueEncoding = this.defaults.valueEncoding
  if (this.defaults.force && opts.force === undefined) opts.force = true
  return opts
}

LevelDat.prototype._assert = function() {
  if (this.change === -1) throw new Error('Database is not ready. Wait for the ready event.')
}

LevelDat.prototype.putMeta = function(key, value, opts, cb) {
  if (typeof opts === 'function') return this.putMeta(key, value, null, opts)
  if (!cb) cb = noop
  opts = this._mixin(opts)

  this.mutex.put(PREFIX_META+key, value, opts, cb)
}

LevelDat.prototype.getMeta = function(key, opts, cb) {
  if (typeof opts === 'function') return this.getMeta(key, null, cb)
  opts = this._mixin(opts)

  var self = this
  this.mutex.afterWrite(function() {
    debug('get meta.%s', key)
    self.mutex.get(PREFIX_META+key, opts, function(err, val) {
      if (err) return cb(err)
      cb(null, val)
    })
  })
}

LevelDat.prototype.count = function(cb) {
  var self = this

  cb = once(cb)
  this.getMeta('_count', {valueEncoding:'json'}, function(err, result) {
    if (!result) result = {count:0, change:0}
    if (result.change === self.change) return cb(null, result.count)

    var changes = self.createChangesReadStream({
      change: result.change
    })

    var persist = function(cb) {
      debug('put meta._count (change: %d, count: %d)', result.change, result.count)
      self.putMeta('_count', result, {valueEncoding:'json'}, function(err) {
        if (err) return cb(err)
        cb(null)
      })
    }

    var inc = 0
    var ondata = function(data, enc, cb) {
      result.change = data.change
      if (data.type === 'create') result.count++
      else if (data.type === 'delete') result.count--
      if (++inc % 5000) cb()
      else persist(cb)
    }

    changes.on('error', cb)
    changes.pipe(through.obj(ondata)).on('finish', function() {
      persist(function() {
        cb(null, result)
      })
    })
  })
}

module.exports = LevelDat<commit_msg>fix change feed option<commit_after>var through = require('through2')
var pumpify = require('pumpify')
var once = require('once')
var lexint = require('lexicographic-integer')
var mutex = require('level-mutex')
var byteStream = require('byte-stream')
var debug = require('debug')('level-dat')
var util = require('util')
var events = require('events')

var noop = function() {}

var TYPES = ['update', 'delete', 'create']

var WRITE_BUFFER_SIZE = 1024 * 1024 * 16
var SEP = '\xff'
var PREFIX = {
  change: 's',
  data: 'd',
  version:  'r',
  cur: 'c',
  meta: 'm'
}

var PREFIX_CHANGE = SEP+PREFIX.change+SEP
var PREFIX_DATA = SEP+PREFIX.data+SEP
var PREFIX_VERSION = SEP+PREFIX.version+SEP
var PREFIX_CUR = SEP+PREFIX.cur+SEP
var PREFIX_META = SEP+PREFIX.meta+SEP

var conflict = function(key, version) {
  var err =  new Error('Key conflict. A row with that key already exists and/or has a newer version.')
  err.key = key
  err.version = version
  err.status = 409
  err.conflict = true
  return err
}

var waiter = function(missing, cb) {
  var done = false
  return function(err) {
    if (done) return
    if (err) {
      done = true
      return cb(err)
    }
    if (--missing) return
    done = true
    cb()
  }
}

var deleted = function(cur) {
  return cur.length > 2 && cur[cur.length-2] === SEP && cur[cur.length-1] === '1'
}

var pack = function(n) {
  return lexint.pack(n, 'hex')
}

var unpack = function(n) {
  return lexint.unpack(n, 'hex')
}

var LevelDat = function(db, opts, onready) {
  if (!(this instanceof LevelDat)) return new LevelDat(db, opts, onready)
  if (typeof opts === 'function') return new LevelDat(db, null, onready)
  if (!opts) opts = {}

  var self = this

  this.db = db
  this.mutex = mutex(db)
  this.change = opts.change || -1
  this.defaults = opts

  this.mutex.peekLast({last:PREFIX_CHANGE+SEP}, function(err, key, value) {
    if (err && err.message !== 'range not found') return self.emit('error', err)

    self.change = value ? JSON.parse(value)[0] : 0
    debug('head change: %d', self.change)
    self.emit('ready', self)
  })

  if (onready) this.on('ready', onready)
}

util.inherits(LevelDat, events.EventEmitter)

LevelDat.prototype.createVersionStream = function(key, opts) {
  opts = this._mixin(opts)
  opts.start = PREFIX_DATA+key+SEP
  opts.end = PREFIX_DATA+key+SEP+SEP

  var stream = through.obj(function(data, enc, cb) {
    var vidx = data.key.lastIndexOf(SEP)

    data = {
      key: data.key.slice(PREFIX_DATA.length, vidx),
      version: unpack(data.key.slice(vidx+1)),
      value: data.value
    }

    debug('get version (key: %s, version: %d)', data.key, data.version)
    cb(null, data)
  })

  var rs = this.db.createReadStream(opts)

  return pumpify.obj(rs, stream)
}

LevelDat.prototype.valueStream =
LevelDat.prototype.createValueStream = function(opts) {
  opts = this._mixin(opts)
  opts.keys = false
  opts.values = true
  return this.createReadStream(opts)
}

LevelDat.prototype.keyStream =
LevelDat.prototype.createKeyStream = function(opts) {
  opts = this._mixin(opts)
  opts.keys = true
  opts.values = false
  return this.createReadStream(opts)
}

LevelDat.prototype.readStream =
LevelDat.prototype.createReadStream = function(opts) {
  opts = this._mixin(opts)

  var self = this
  var keys = opts.keys !== false
  var values = opts.values !== false

  var rs = self.db.createReadStream({
    start: PREFIX_CUR+(opts.start || ''),
    end: PREFIX_CUR+(opts.end || SEP)
  })

  var get = through.obj(function(data, enc, cb) {
    var val = data.value
    var key = data.key.slice(PREFIX_CUR.length)

    if (deleted(val)) return cb()

    var version = unpack(val)
    self.mutex.get(PREFIX_DATA+key+SEP+val, opts, function(err, data) {
      if (err) return cb(err)
      debug('get data.%s (version: %d)', key, version)

      if (values && !keys) return cb(null, data)
      if (keys && !values) return cb(null, key)

      cb(null, {
        key: key,
        version: version,
        value: data
      })
    })
  })

  return pumpify.obj(rs, get)
}

LevelDat.prototype.writeStream =
LevelDat.prototype.createWriteStream = function(opts) {
  this._assert()
  opts = this._mixin(opts)

  var self = this

  var buffer = byteStream({
    limit: WRITE_BUFFER_SIZE,
    time: 3000
  })

  var format = through.obj(function(data, enc, cb) {
    data.length = data.value ? data.value.length || 1 : 1
    cb(null, data)
  })

  var ws = through.obj(function(batch, enc, cb) {
    self.batch(batch, cb)
  })

  return pumpify.obj(format, buffer, ws)
}

LevelDat.prototype.createChangesWriteStream = function(opts) {
  this._assert()
  opts = this._mixin(opts)

  var self = this

  var buffer = byteStream({
    limit: WRITE_BUFFER_SIZE,
    time: 3000
  })

  var format = through.obj(function(data, enc, cb) {
    if (!data.value && data.type !== 'delete') return cb(new Error('data.value is required'))
    data.length = data.value ? data.value.length || 1 : 1
    cb(null, data)
  })

  var ws = through.obj(function(batch, enc, cb) {
    var wait = waiter(batch.length, cb)

    for (var i = 0; i < batch.length; i++) {
      var b = batch[i]
      var v = pack(b.version)

      debug('put change (change: %d, key: %s, version: %d, type: %s)', b.change, b.key, b.version, b.type)

      if (b.type === 'delete') {
        self.mutex.put(PREFIX_CHANGE+pack(b.change), JSON.stringify([b.change, b.key, b.version, 'delete']), noop)
        self.mutex.put(PREFIX_CUR+b.key, v+SEP+'1', wait)
      } else {
        self.mutex.put(PREFIX_CHANGE+pack(b.change), JSON.stringify([b.change, b.key, b.version, b.type]), noop)
        self.mutex.put(PREFIX_CUR+b.key, v, noop)
        self.mutex.put(PREFIX_DATA+b.key+SEP+v, b.value, opts, wait)
      }
    }
  })

  return pumpify.obj(format, buffer, ws)
}

LevelDat.prototype.createChangesReadStream = function(opts) {
  opts = this._mixin(opts)

  var self = this
  var addData = !!opts.data
  var since = opts.since || 0

  var rs = this.db.createReadStream({
    start: PREFIX_CHANGE+pack(since),
    end: PREFIX_CHANGE+SEP
  })

  var format = through.obj(function(data, enc, cb) {
    var value = JSON.parse(data.value)
    if (value[0] === since) return cb()

    var data = {
      key: value[1],
      version: value[2],
      change: value[0],
      type: value[3]
    }

    debug('get change (change: %d, key: %s, version: %d, type: %s, data: %s)', data.change, data.key, data.version, data.type, addData)
    if (!addData || data.type === 'delete') return cb(null, data)

    self._get(data.key, opts, data.version, function(err, value) {
      if (err) return cb(err)
      data.value = value
      cb(null, data)
    })
  })

  return pumpify.obj(rs, format)
}

LevelDat.prototype.get = function(key, opts, cb, version) {
  if (typeof opts === 'function') return this.get(key, null, opts)
  opts = this._mixin(opts)

  if (!opts.version) this._getLatest(key, opts, cb)
  else this._get(key, opts, opts.version, cb)
}

LevelDat.prototype._getLatest = function(key, opts, cb) {
  opts = this._mixin(opts)

  var self = this
  this.mutex.get(PREFIX_CUR+key, function(err, cur) {
    if (err) return cb(err)
    if (deleted(cur)) return cb(new Error('Key was deleted'))

    self._get(key, opts, unpack(cur), cb)
  })
}

LevelDat.prototype._get = function(key, opts, version, cb) {
  opts = this._mixin(opts)
  version = +version

  this.mutex.get(PREFIX_DATA+key+SEP+pack(version), opts, function(err, val) {
    if (err) return cb(err)

    debug('get data.%s (version: %d)', key, version)
    cb(null, val, version)
  })
}

LevelDat.prototype.put = function(key, value, opts, cb) {
  this._assert()
  if (typeof opts === 'function') return this.put(key, value, null, opts)
  if (!cb) cb = noop
  opts = this._mixin(opts)

  this._put(key, value, opts, opts.version, cb)
}

LevelDat.prototype.batch = function(batch, opts, cb) {
  if (typeof opts === 'function') return this.batch(batch, null, opts)
  if (!cb) cb = noop
  opts = this._mixin(opts)

  if (!batch.length) return cb()
  var wait = waiter(batch.length, cb)

  for (var i = 0; i < batch.length; i++) {
    var b = batch[i]
    if (b.type === 'delete') this.del(b.key, wait)
    else this._put(b.key, b.value, opts, b.version || 0, wait)
  }
}

LevelDat.prototype._put = function(key, value, opts, version, cb) {
  this._assert()
  var autoVersion = !version
  if (!version) version = 1
  opts = this._mixin(opts)

  var self = this

  this.mutex.get(PREFIX_CUR+key, function(_, curV) {
    if (curV) curV = unpack(curV)
    if (curV) debug('put data.%s existing version exist (old-version: %d, new-version: %d)', key, curV, version)

    if (version === curV && autoVersion && !opts.force) return cb(conflict(key, version))
    if (version < curV && !opts.force) return cb(conflict(key, version))
    if (version === curV) version++

    var v = pack(+version)
    var change = ++self.change

    debug('put data.%s (version: %d)', key, version)
    self.mutex.put(PREFIX_CHANGE+pack(change), JSON.stringify([change, key, version, curV ? 'update' : 'create']), noop)
    self.mutex.put(PREFIX_CUR+key, v, noop)
    self.mutex.put(PREFIX_DATA+key+SEP+v, value, opts, cb)
  })
}

LevelDat.prototype.del =
LevelDat.prototype.delete = function(key, cb) {
  this._assert()
  if (!cb) cb = noop

  var self = this

  this.mutex.get(PREFIX_CUR+key, function(err, v) {
    if (err) return cb(err)

    var change = ++self.change
    var version = unpack(v)

    debug('del data.%s', key)
    self.mutex.put(PREFIX_CHANGE+pack(change), JSON.stringify([change, key, version, 'delete']), noop)
    self.mutex.put(PREFIX_CUR+key, v+SEP+'1', cb)
  })
}

LevelDat.prototype._mixin = function(opts) {
  if (!opts) opts = {}
  if (!opts.valueEncoding) opts.valueEncoding = this.defaults.valueEncoding
  if (this.defaults.force && opts.force === undefined) opts.force = true
  return opts
}

LevelDat.prototype._assert = function() {
  if (this.change === -1) throw new Error('Database is not ready. Wait for the ready event.')
}

LevelDat.prototype.putMeta = function(key, value, opts, cb) {
  if (typeof opts === 'function') return this.putMeta(key, value, null, opts)
  if (!cb) cb = noop
  opts = this._mixin(opts)

  this.mutex.put(PREFIX_META+key, value, opts, cb)
}

LevelDat.prototype.getMeta = function(key, opts, cb) {
  if (typeof opts === 'function') return this.getMeta(key, null, cb)
  opts = this._mixin(opts)

  var self = this
  this.mutex.afterWrite(function() {
    debug('get meta.%s', key)
    self.mutex.get(PREFIX_META+key, opts, function(err, val) {
      if (err) return cb(err)
      cb(null, val)
    })
  })
}

LevelDat.prototype.count = function(cb) {
  var self = this

  cb = once(cb)
  this.getMeta('_count', {valueEncoding:'json'}, function(err, result) {
    if (!result) result = {count:0, change:0}
    if (result.change === self.change) return cb(null, result.count)

    var changes = self.createChangesReadStream({
      since: result.change
    })

    var persist = function(cb) {
      debug('put meta._count (change: %d, count: %d)', result.change, result.count)
      self.putMeta('_count', result, {valueEncoding:'json'}, function(err) {
        if (err) return cb(err)
        cb(null)
      })
    }

    var inc = 0
    var ondata = function(data, enc, cb) {
      result.change = data.change
      if (data.type === 'create') result.count++
      else if (data.type === 'delete') result.count--
      if (++inc % 5000) cb()
      else persist(cb)
    }

    changes.on('error', cb)
    changes.pipe(through.obj(ondata)).on('finish', function() {
      persist(function() {
        cb(null, result.count)
      })
    })
  })
}

module.exports = LevelDat<|endoftext|>


<commit_before>// Homebridge Plugin for Mode Lighting System using Remote Control Interface
// Need to enhance with more error checking
var request = require('request');

var Service, Characteristic;

module.exports = function(homebridge) {

  // Service and Characteristic are from hap-nodejs
  Service = homebridge.hap.Service;
  Characteristic = homebridge.hap.Characteristic;
  homebridge.registerAccessory("homebridge-modelighting", "modelighting",
    ModeLightingAccessory);
}

function ModeLightingAccessory(log, config) {
  this.log = log;

  // Get Room Name from config.json
  this.name = config["name"];

  // Get Mode Lighting On/Off Scene Numbers for Room Name and
  // NPU IP Address from config.json
  this.on_scene = config["on_scene"];
  this.off_scene = config["off_scene"];
  this.NPU_IP = config["NPU_IP"];
}

ModeLightingAccessory.prototype = {

  setPowerState: function(powerOn, callback) {

    var scene;

    var NPU_IP = this.NPU_IP;

    if (powerOn) {
      scene = this.on_scene;
      this.log("setPowerState: Invoking on scene");
    } else {
      scene = this.off_scene;
      this.log("setPowerState: Invoking off scene");
    }

    request.post(
      'http://' + NPU_IP + '/gateway?', {
        json: {
          contentType: 'text/plain',
          dataType: 'text',
          data: '$scnrecall,' + scene + ';'
        }
      },
      function(error, response, body) {
        if (!error && response.statusCode == 200) {
          console.log(body);
        }
      }
    );

    callback(null);

    return (0);
  },

  getPowerState: function(callback) {

    var scene = this.on_scene;

    var NPU_IP = this.NPU_IP;

    request.post(
      'http://' + NPU_IP + '/gateway?', {
        json: {
          contentType: 'text/plain',
          dataType: 'text',
					timeout: 1500,
          data: '?scn,' + scene + ';'
        }
      },
      function(error, response, body) {

        console.log('getPowerState: Error is: ' + error);
				console.log('getPowerState: Error Code is: ' + error.code);
        console.log('getPowerState: Response is: ' + response);
				// console.log('getPowerState: Response Status is: ' + response.statusCode);
        console.log('getPowerState: Body is: ' + body);

        if (!error && response.statusCode == 200) {
          console.log(body);
        }

        if (body == null) {
          console.log('Body is null');
					console.log('Error Code is: '+ error.code)
        } else if (body != "") {
          // Get Light Status & Return through callback
          var pos = body.lastIndexOf(";");
          callback(null, body.substring(pos - 5, pos - 4));
        } else {
          console.log('Body from webserver was blank!');
        }
      }
    );

    return (0);
  },

  identify: function(callback) {
    this.log("identify: Identify requested!");
    callback(); // success
  },

  getServices: function() {

    // you can OPTIONALLY create an information service if you wish to override
    // the default values for things like serial number, model, etc.
    var informationService = new Service.AccessoryInformation();

    informationService
      .setCharacteristic(Characteristic.Manufacturer, "Mode Lighting")
      .setCharacteristic(Characteristic.Model, "NPU SW000120.2.3.6.3")
      .setCharacteristic(Characteristic.SerialNumber, "");

    var switchService = new Service.Switch(this.name);

    switchService
      .getCharacteristic(Characteristic.On)
      .on('set', this.setPowerState.bind(this))
      .on('get', this.getPowerState.bind(this));

    return [switchService];
  }
};
<commit_msg>debugging<commit_after>// Homebridge Plugin for Mode Lighting System using Remote Control Interface
// Need to enhance with more error checking
var request = require('request');

var Service, Characteristic;

module.exports = function(homebridge) {

  // Service and Characteristic are from hap-nodejs
  Service = homebridge.hap.Service;
  Characteristic = homebridge.hap.Characteristic;
  homebridge.registerAccessory("homebridge-modelighting", "modelighting",
    ModeLightingAccessory);
}

function ModeLightingAccessory(log, config) {
  this.log = log;

  // Get Room Name from config.json
  this.name = config["name"];

  // Get Mode Lighting On/Off Scene Numbers for Room Name and
  // NPU IP Address from config.json
  this.on_scene = config["on_scene"];
  this.off_scene = config["off_scene"];
  this.NPU_IP = config["NPU_IP"];
}

ModeLightingAccessory.prototype = {

  setPowerState: function(powerOn, callback) {

    var scene;

    var NPU_IP = this.NPU_IP;

    if (powerOn) {
      scene = this.on_scene;
      this.log("setPowerState: Invoking on scene");
    } else {
      scene = this.off_scene;
      this.log("setPowerState: Invoking off scene");
    }

    request.post(
      'http://' + NPU_IP + '/gateway?', {
        json: {
          contentType: 'text/plain',
          dataType: 'text',
          data: '$scnrecall,' + scene + ';'
        }
      },
      function(error, response, body) {
        if (!error && response.statusCode == 200) {
          console.log(body);
        }
      }
    );

    callback(null);

    return (0);
  },

  getPowerState: function(callback) {

    var scene = this.on_scene;

    var NPU_IP = this.NPU_IP;

    request.post(
      'http://' + NPU_IP + '/gateway?', {
        json: {
          contentType: 'text/plain',
          dataType: 'text',
					timeout: 1500,
          data: '?scn,' + scene + ';'
        }
      },
      function(error, response, body) {

        console.log('getPowerState: Error is: ' + error);
				console.log('getPowerState: Error Code is: ' + error.code)
        console.log('getPowerState: Response is: ' + response);
        console.log('getPowerState: Body is: ' + body);

        if (!error && response.statusCode == 200) {
          console.log(body);
        }

        if (body == null) {
          console.log('Body is null');
        } else if (body != "") {
          // Get Light Status & Return through callback
          var pos = body.lastIndexOf(";");
          callback(null, body.substring(pos - 5, pos - 4));
        } else {
          console.log('Body from webserver was blank!');
        }
      }
    );

    return (0);
  },

  identify: function(callback) {
    this.log("identify: Identify requested!");
    callback(); // success
  },

  getServices: function() {

    // you can OPTIONALLY create an information service if you wish to override
    // the default values for things like serial number, model, etc.
    var informationService = new Service.AccessoryInformation();

    informationService
      .setCharacteristic(Characteristic.Manufacturer, "Mode Lighting")
      .setCharacteristic(Characteristic.Model, "NPU SW000120.2.3.6.3")
      .setCharacteristic(Characteristic.SerialNumber, "");

    var switchService = new Service.Switch(this.name);

    switchService
      .getCharacteristic(Characteristic.On)
      .on('set', this.setPowerState.bind(this))
      .on('get', this.getPowerState.bind(this));

    return [switchService];
  }
};
<|endoftext|>