<commit_before>/**
 * Copyright (c) 2017 Ali Lokhandwala <ali@huestones.co.uk>. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const path = require('path');
const fs = require('fs');
const program = require('commander');
const _ = require('lodash');
const debug = require('debug')('app:watsncv');
const pkg = require('./package.json');

exports = module.exports = main;
main.setupServices = setupServices;

//--

function main() {
  program.version(pkg.version);
  setupServices(program);

  var normalizedPath = path.join(__dirname, 'src', 'cassettes');

  program.debug('Loading cassettes from %s', normalizedPath);

  fs.readdirSync(normalizedPath)
    .filter(filename => /\.js$/i.test(filename))
    .forEach((file) => {
      var fp = path.join(normalizedPath, file);
      var stat = fs.statSync(fp);
      if (stat.isFile()) {

        program.debug('Loading \'%s\'', fp);

        var cassette = require(fp);
        cassette.load(program);
      } else {
        program.debug('Skipped \'%s\', not a file', fp);
      }
    });

  try {
    program.parse(process.argv);
  } catch (e) {
    program.error(e);
  }

  if (!process.argv.slice(2).length) {
    program.help();
  }

  return program;
}

function setupServices(program) {
  program.debug = debug;

  program.error = (e => {
    console.error(e.message);
    process.exit(1);
  });

  program.out = console.log;

  program.play = (f => _.wrap(program, f));
}
<commit_msg>no command displays help<commit_after>/**
 * Copyright (c) 2017 Ali Lokhandwala <ali@huestones.co.uk>. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const path = require('path');
const fs = require('fs');
const program = require('commander');
const _ = require('lodash');
const debug = require('debug')('app:watsncv');
const pkg = require('./package.json');

exports = module.exports = main;
main.setupServices = setupServices;

//--

function main() {
  program.version(pkg.version);
  setupServices(program);

  var normalizedPath = path.join(__dirname, 'src', 'cassettes');

  program.debug('Loading cassettes from %s', normalizedPath);

  fs.readdirSync(normalizedPath)
    .filter(filename => /\.js$/i.test(filename))
    .forEach((file) => {
      var fp = path.join(normalizedPath, file);
      var stat = fs.statSync(fp);
      if (stat.isFile()) {

        program.debug('Loading \'%s\'', fp);

        var cassette = require(fp);
        cassette.load(program);
      } else {
        program.debug('Skipped \'%s\', not a file', fp);
      }
    });

  program.on('*', () => program.help());

  try {
    program.parse(process.argv);
  } catch (e) {
    program.error(e);
  }

  if (!process.argv.slice(2).length) {
    program.help();
  }

  return program;
}

function setupServices(program) {
  program.debug = debug;

  program.error = (e => {
    console.error(e.message);
    process.exit(1);
  });

  program.out = console.log;

  program.play = (f => _.wrap(program, f));
}
<|endoftext|>


<commit_before>/*
 * Iopa Database Firebase Middleware
 * Copyright (c) 2017 Internet of Protocols Alliance
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const firebase = require("firebase/app");
require("firebase/auth");
require("firebase/database");

var EventEmitter;
var FIREBASE_INITIALIZED = false

function FirebaseMiddleware(app) {

  if (process.env.BROWSER) {
    EventEmitter = function () { throw Error("Not implemented in browser") };
  } else {
    EventEmitter = require('events');
  }

  this.app = app;

  if (!FIREBASE_INITIALIZED) {

    if (process.env.BROWSER) {
      firebase.initializeApp({
        apiKey: process.env.FIREBASE_API_KEY,
        authDomain: process.env.FIREBASE_AUTH_DOMAIN,
        databaseURL: process.env.FIREBASE_DATABASE_URL,
        storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID
      });

      firebase.auth().onAuthStateChanged(user => {
        console.log("onAuthStateChanged", user);
        if (user === null) {
          firebase.auth().signInAnonymously().then((result) => {
            console.log("signInAnonymously", result);

          }).catch(error => {
            console.log("signInAnonymously", "error", error);
          });
        }
      });
    } else {
      firebase.initializeApp({
        serviceAccount: {
          projectId: process.env.FIREBASE_PROJECT_ID,
          clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
          privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n')
        },
        databaseURL: process.env.FIREBASE_DATABASE_URL
      });
    }

    FIREBASE_INITIALIZED = true;

  }

  var root = process.env.FIREBASE_ROOT || "/";
  var dbref = firebase.database().ref(root);

  this.dbref = dbref;

  app.properties["server.Capabilities"]["urn:io.iopa.database"] = {

    get: function (path) {
      return new Promise(function (resolve, reject) {
        var itemRef = dbref.child(path);

        itemRef.once("value", function (snapshot) {
          var item = snapshot.val();
          resolve(item);
          itemRef = null;
        }, function (errorObject) {
          reject(errorObject.code);
        });
      });
    },
    push: function (path, blob) {
      var itemRef = dbref.child(path).push();
      blob.timestamp = firebase.database.ServerValue.TIMESTAMP;
      itemRef.set(blob);
      itemRef = null;
    },
    put: function (path, blob) {
      var itemRef = dbref.child(path);
      if (blob)
        blob.timestamp = firebase.database.ServerValue.TIMESTAMP;
      itemRef.set(blob);
    },
    subscribe: function (path, callback) {

      var result;

      if (!callback) {
        result = new EventEmitter();
        callback = (result.emit.bind(this, "value"));
      }

      var itemRef = dbref.child(path);

      itemRef.on("value", function (snapshot) {
        var item = snapshot.val();
        if (!item.key)
          item.key = snapshot.key();
        callback(item);
      }, function (errorObject) {
        // ignore
      });

      return result;
    },
    subscribechanges: function (path, store) {

      var dbadd, dbremove, dbupdate, result;

      if (store) {
        dbadd = store.dbadd.bind(this);
        dbremove = store.dbremove.bind(this);
        dbupdate = store.dbupdate.bind(this);
      } else {
        result = new EventEmitter();
        dbadd = result.emit.bind(this, "value");
        dbremove = result.emit.bind(this, "removed");
        dbupdate = result.emit.bind(this, "updated");
      }

      var itemRef = dbref.child(path);

      itemRef.orderByChild('timestamp').startAt(Date.now()).on('child_added', function (snapshot) {
        if (!item.key)
          item.key = snapshot.key();
        var item = snapshot.val();
        store.dbadd(item);
      });

      itemRef.on('child_removed', function (snapshot) {
        var item = snapshot.val();
        if (!item.key)
          item.key = snapshot.key();
        store.dbremove(item);
      });

      itemRef.on('child_updated', function (snapshot) {
        var item = snapshot.val();
        if (!item.key)
          item.key = snapshot.key();
        store.dbupdate(item);
      });

      return result;
    }
  }
  app.properties["server.Capabilities"]["urn:io.iopa.database"]["iopa.Version"] = "1.4";

}

FirebaseMiddleware.prototype.invoke = function (context, next) {
  context.db = context.db || this.app.properties["server.Capabilities"]["urn:io.iopa.database"];
  return next();
}

module.exports = FirebaseMiddleware;<commit_msg>removed arrow functions<commit_after>/*
 * Iopa Database Firebase Middleware
 * Copyright (c) 2017 Internet of Protocols Alliance
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const firebase = require("firebase/app");
require("firebase/auth");
require("firebase/database");

var EventEmitter;
var FIREBASE_INITIALIZED = false

function FirebaseMiddleware(app) {

  if (process.env.BROWSER) {
    EventEmitter = function () { throw Error("Not implemented in browser") };
  } else {
    EventEmitter = require('events');
  }

  this.app = app;

  if (!FIREBASE_INITIALIZED) {

    if (process.env.BROWSER) {
      firebase.initializeApp({
        apiKey: process.env.FIREBASE_API_KEY,
        authDomain: process.env.FIREBASE_AUTH_DOMAIN,
        databaseURL: process.env.FIREBASE_DATABASE_URL,
        storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID
      });

      firebase.auth().onAuthStateChanged(function(user) {
        console.log("onAuthStateChanged", user);
        if (user === null) {
          firebase.auth().signInAnonymously().then(function(result) {
            console.log("signInAnonymously", result);

          }).catch(function(error) {
            console.log("signInAnonymously", "error", error);
          });
        }
      });
    } else {
      firebase.initializeApp({
        serviceAccount: {
          projectId: process.env.FIREBASE_PROJECT_ID,
          clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
          privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n')
        },
        databaseURL: process.env.FIREBASE_DATABASE_URL
      });
    }

    FIREBASE_INITIALIZED = true;

  }

  var root = process.env.FIREBASE_ROOT || "/";
  var dbref = firebase.database().ref(root);

  this.dbref = dbref;

  app.properties["server.Capabilities"]["urn:io.iopa.database"] = {

    get: function (path) {
      return new Promise(function (resolve, reject) {
        var itemRef = dbref.child(path);

        itemRef.once("value", function (snapshot) {
          var item = snapshot.val();
          resolve(item);
          itemRef = null;
        }, function (errorObject) {
          reject(errorObject.code);
        });
      });
    },
    push: function (path, blob) {
      var itemRef = dbref.child(path).push();
      blob.timestamp = firebase.database.ServerValue.TIMESTAMP;
      itemRef.set(blob);
      itemRef = null;
    },
    put: function (path, blob) {
      var itemRef = dbref.child(path);
      if (blob)
        blob.timestamp = firebase.database.ServerValue.TIMESTAMP;
      itemRef.set(blob);
    },
    subscribe: function (path, callback) {

      var result;

      if (!callback) {
        result = new EventEmitter();
        callback = (result.emit.bind(this, "value"));
      }

      var itemRef = dbref.child(path);

      itemRef.on("value", function (snapshot) {
        var item = snapshot.val();
        if (!item.key)
          item.key = snapshot.key();
        callback(item);
      }, function (errorObject) {
        // ignore
      });

      return result;
    },
    subscribechanges: function (path, store) {

      var dbadd, dbremove, dbupdate, result;

      if (store) {
        dbadd = store.dbadd.bind(this);
        dbremove = store.dbremove.bind(this);
        dbupdate = store.dbupdate.bind(this);
      } else {
        result = new EventEmitter();
        dbadd = result.emit.bind(this, "value");
        dbremove = result.emit.bind(this, "removed");
        dbupdate = result.emit.bind(this, "updated");
      }

      var itemRef = dbref.child(path);

      itemRef.orderByChild('timestamp').startAt(Date.now()).on('child_added', function (snapshot) {
        if (!item.key)
          item.key = snapshot.key();
        var item = snapshot.val();
        store.dbadd(item);
      });

      itemRef.on('child_removed', function (snapshot) {
        var item = snapshot.val();
        if (!item.key)
          item.key = snapshot.key();
        store.dbremove(item);
      });

      itemRef.on('child_updated', function (snapshot) {
        var item = snapshot.val();
        if (!item.key)
          item.key = snapshot.key();
        store.dbupdate(item);
      });

      return result;
    }
  }
  app.properties["server.Capabilities"]["urn:io.iopa.database"]["iopa.Version"] = "1.4";

}

FirebaseMiddleware.prototype.invoke = function (context, next) {
  context.db = context.db || this.app.properties["server.Capabilities"]["urn:io.iopa.database"];
  return next();
}

module.exports = FirebaseMiddleware;<|endoftext|>


<commit_before>var Base = require('ribcage-view')
  , BackButton = require('ribcage-back-button')
  , Button = require('ribcage-button')
  , Menu = require('ribcage-menu')

var TopBar = Base.extend({

  afterInit: function (opts) {
    this.options = opts
  }

, events: {
    'click .left-button-target': 'propagateLeft'
  , 'click .right-button-target': 'propagateRight'
  }

, template: function () {
    return ''+
      '

'+
      '

'+
      '

'+
      '

'
  }

, propagateLeft: function (e) {
    if(this.leftButton && e.target.classList.contains('left-button-target')) {
      e.stopPropagation()
      this.leftButton.$el.triggerHandler('click')
    }
  }

, propagateRight: function (e) {
    if(this.rightButton && e.target.classList.contains('right-button-target')) {
      e.stopPropagation()
      this.rightButton.$el.triggerHandler('click')
    }
  }

, className: 'top-bar'

, afterRender: function () {

    var opts = this.options

    if (opts.left) this.setLeftButton(opts.left)
    if (opts.title) this.setTitle(opts.title, {show: true})
    if (opts.menu) this.setMenu(opts.menu, {show: true})
    if (opts.right) this.setRightButton(opts.right)

    this.eachSubview(function (subview) {
      subview.render();
      subview.delegateEvents();
    });

  }

, getButton: function (opts) {

    // someone may have passed in an already built button
    // if so, just append it now
    if (typeof opts.render == 'function') {
      return opts
    }

    var button;

    if(opts.type == 'back')
      button = new BackButton(opts);
    else
      button = new Button(opts);

    return button;
  }

, setLeftButton: function (btn) {

    if (this.leftButton) this.leftButton.close()

    this.leftButton = this.getButton(btn)
    this.leftButton.$el.addClass('left')
    this.appendSubview(this.leftButton, this.$('.left-button-target'))

  }

, setRightButton: function (btn) {

    if (this.rightButton) this.rightButton.close()

    if (!btn) return

    this.rightButton = this.getButton(btn)
    this.rightButton.$el.addClass('right')
    this.appendSubview(this.rightButton, this.$('.right-button-target'))

  }

, setMenu: function (opts, params) {

    if (!params) params = {}

    if (this.menu) this.menu.close()

    this.menu = new Menu(opts)
    this.appendSubview(this.menu, this.$('.menu-target'))

    if (params.show) this.showMenu()

  }

, hideMenu: function () {
    this.$('.menu-target').hide()
  }

, showMenu: function () {
    this.$('.menu-target').show()
    this.$('.title').hide()
  }

, setTitle: function (title, params) {
    if (!params) params = {}

    if(typeof title == 'string')
      this.$('.title').html(title)
    else
      this.appendSubview(title, this.$('.title'));

    if (params.show) this.showTitle()
  }

, hideTitle: function () {
    this.$('.title').hide()
  }

, showTitle: function () {
    this.$('.title').show()
    this.$('.menu-target').hide()
  }

, activateMenuItem: function (route) {
    this.menu.$('.active').removeClass('active')
    this.menu.eachSubview(function (view) {
      if (view.options.route == route) view.$el.addClass('active')
    })
  }

})

module.exports = TopBar
<commit_msg>Removes back button<commit_after>var Base = require('ribcage-view')
  , Button = require('ribcage-button')
  , Menu = require('ribcage-menu')

var TopBar = Base.extend({

  afterInit: function (opts) {
    this.options = opts
  }

, events: {
    'click .left-button-target': 'propagateLeft'
  , 'click .right-button-target': 'propagateRight'
  }

, template: function () {
    return ''+
      '

'+
      '

'+
      '

'+
      '

'
  }

, propagateLeft: function (e) {
    if(this.leftButton && e.target.classList.contains('left-button-target')) {
      e.stopPropagation()
      this.leftButton.$el.triggerHandler('click')
    }
  }

, propagateRight: function (e) {
    if(this.rightButton && e.target.classList.contains('right-button-target')) {
      e.stopPropagation()
      this.rightButton.$el.triggerHandler('click')
    }
  }

, className: 'top-bar'

, afterRender: function () {

    var opts = this.options

    if (opts.left) this.setLeftButton(opts.left)
    if (opts.title) this.setTitle(opts.title, {show: true})
    if (opts.menu) this.setMenu(opts.menu, {show: true})
    if (opts.right) this.setRightButton(opts.right)

    this.eachSubview(function (subview) {
      subview.render();
      subview.delegateEvents();
    });

  }

, getButton: function (opts) {

    // someone may have passed in an already built button
    // if so, just append it now
    if (typeof opts.render == 'function') {
      return opts
    }

    return new Button(opts)
  }

, setLeftButton: function (btn) {

    if (this.leftButton) this.leftButton.close()

    this.leftButton = this.getButton(btn)
    this.leftButton.$el.addClass('left')
    this.appendSubview(this.leftButton, this.$('.left-button-target'))

  }

, setRightButton: function (btn) {

    if (this.rightButton) this.rightButton.close()

    if (!btn) return

    this.rightButton = this.getButton(btn)
    this.rightButton.$el.addClass('right')
    this.appendSubview(this.rightButton, this.$('.right-button-target'))

  }

, setMenu: function (opts, params) {

    if (!params) params = {}

    if (this.menu) this.menu.close()

    this.menu = new Menu(opts)
    this.appendSubview(this.menu, this.$('.menu-target'))

    if (params.show) this.showMenu()

  }

, hideMenu: function () {
    this.$('.menu-target').hide()
  }

, showMenu: function () {
    this.$('.menu-target').show()
    this.$('.title').hide()
  }

, setTitle: function (title, params) {
    if (!params) params = {}

    if(typeof title == 'string')
      this.$('.title').html(title)
    else
      this.appendSubview(title, this.$('.title'));

    if (params.show) this.showTitle()
  }

, hideTitle: function () {
    this.$('.title').hide()
  }

, showTitle: function () {
    this.$('.title').show()
    this.$('.menu-target').hide()
  }

, activateMenuItem: function (route) {
    this.menu.$('.active').removeClass('active')
    this.menu.eachSubview(function (view) {
      if (view.options.route == route) view.$el.addClass('active')
    })
  }

})

module.exports = TopBar
<|endoftext|>


<commit_before>#!/usr/bin/env node
const fs = require('fs');
const schedule = require('node-schedule');
const RtmClient = require('@slack/client').RtmClient;
const WebClient = require('@slack/client').WebClient;
const CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;

const config = require('./config.json');
const reminders = require('./reminders.json');

/**
 * Arianna - Zero Daedalus Slackbot
 * @module  arianna
 */

console.log('Arianna Running...');

const token = config.SLACK_TOKEN || '';
const rtm = new RtmClient(token);
const web = new WebClient(token);

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (data) => {
  console.log(`Logged in as ${data.self.name} of team ${data.team.name}, but not yet connected to a channel`);
});

rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, () => {
  rtm.sendMessage('Back online...', config.SLACK_CHANNEL);
  reminder();
  quote();
});

// Schedule Repeated Tasks
schedule.scheduleJob('0 */7 * * *', reminder);
schedule.scheduleJob('0 10 * * *', quote);

// Watch Slack
rtm.start();

// Handle Exits
process.on('SIGINT', handleExit);

/**
 * Functions
 */

// Send a personalized motivational reminder to me
function reminder() {
  const day = (new Date()).getDay();

  rtm.sendMessage(reminders.messages[day], reminders.channel);
}

// Posts a random quote from the quotes file
function quote() {
  fs.readFile('quotes.txt', 'utf8', (err, data) => {
    if (err) {
      console.log(err);
    } else {
      const lines = data.split('\n');
      const rand = Math.floor(Math.random() * lines.length);

      const quote = lines[rand].match(/".+"/g)[0].slice(1, -1);
      rtm.sendMessage(`> *_${quote}_*`, config.SLACK_CHANNEL);
    }
  });
}

// Alerts the channel that the bot is down.
function handleExit() {
  web.chat.postMessage(config.SLACK_CHANNEL, 'Going offline...', { as_user: true }, (err) => {
    process.exit(err ? 1 : 0);
  });
}<commit_msg>Pull changes for release bump<commit_after>#!/usr/bin/env node
const fs = require('fs');
const schedule = require('node-schedule');
const RtmClient = require('@slack/client').RtmClient;
const WebClient = require('@slack/client').WebClient;
const CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;

const config = require('./config.json');
const reminders = require('./reminders.json');

/**
 * Arianna - Zero Daedalus Slackbot
 * @module  arianna
 */

console.log('Arianna Running...');

const token = config.SLACK_TOKEN || '';
const rtm = new RtmClient(token);
const web = new WebClient(token);

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (data) => {
  console.log(`Logged in as ${data.self.name} of team ${data.team.name}, but not yet connected to a channel`);
});

rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, () => {
  rtm.sendMessage('Back online...', config.SLACK_CHANNEL);
});

// Schedule Repeated Tasks
schedule.scheduleJob('0 */4 * * *', reminder);
schedule.scheduleJob('0 10 * * *', quote);

// Watch Slack
rtm.start();

// Handle Exits
process.on('exit', handleExit);

/**
 * Functions
 */

// Send a personalized motivational reminder to me
function reminder() {
  const day = (new Date()).getDay();

  rtm.sendMessage(reminders.messages[day], reminders.channel);
}

// Posts a random quote from the quotes file
function quote() {
  fs.readFile('quotes.txt', 'utf8', (err, data) => {
    if (err) {
      console.log(err);
    } else {
      const lines = data.split('\n');
      const rand = Math.floor(Math.random() * lines.length);

      const quote = lines[rand].match(/".+"/g)[0].slice(1, -1);
      rtm.sendMessage(`> *_${quote}_*`, config.SLACK_CHANNEL);
    }
  });
}

// Alerts the channel that the bot is down.
function handleExit() {
  web.chat.postMessage(config.SLACK_CHANNEL, 'Going offline...', { as_user: true }, () => {
    console.log('Goodbye!');
  });
}<|endoftext|>


<commit_before>
var oauth2 = require('./oauth2')

module.exports = function (args) {

  var seneca = args.seneca;
  var app = args.app;
  var opts = args.options;

  var oauth2srv = oauth2.init({seneca:seneca, options:opts})

  var userent = seneca.make('sys/user')
  var clientent = seneca.make('application')
  var accesstokenent = seneca.make('accesstoken')

  function buildClientContext(req, res, next) {
    if( !req.body ) return next();

    var clientId = req.body['client_id']
    var clientSecret = req.body['client_secret']

    if( clientId && clientSecret ) {
      clientent.load$({appid:clientId,secret:clientSecret},function(err,client){
        if(err) return next(err);
        req.user = client
        next()
      })
    }
    else return next();
  };

  function info(req, res, next) {
    var access_token = req.query.access_token
    if( !access_token ) {
      access_token = req.headers.authorization
      if( access_token ) {
        access_token = access_token.substring('Bearer '.length)
      }
    }

    if( access_token ) {
      accesstokenent.load$(access_token,function(err,at){
      	if(err) return next(err);
      	if (at) {
          userent.load$(at.userID, function(err, user){
            if(user) {
              res.send({email:user.email, nick:user.nick, name:user.name, image:user.image, active:user.active, confirmed:user.confirmed})
            }
            else {
              res.send(400, "Invalid access token")
            }
          })
      	} else {
      		res.send(400, "Invalid access token")
      	}
      })
    }
    else res.send(400, "Missing access token")
  };

  app.use(buildClientContext);

  app.get('/dialog/authorize', oauth2srv.authorization);
  app.post('/dialog/authorize/decision', oauth2srv.decision);
  app.post('/oauth/token', oauth2srv.token);
  app.get('/api/userinfo', info);

  return {
    buildClientContext: buildClientContext,
    info: info
  };

}<commit_msg>Changed userinfo API endpoint to include version number<commit_after>
var oauth2 = require('./oauth2')

module.exports = function (args) {

  var seneca = args.seneca;
  var app = args.app;
  var opts = args.options;

  var oauth2srv = oauth2.init({seneca:seneca, options:opts})

  var userent = seneca.make('sys/user')
  var clientent = seneca.make('application')
  var accesstokenent = seneca.make('accesstoken')

  function buildClientContext(req, res, next) {
    if( !req.body ) return next();

    var clientId = req.body['client_id']
    var clientSecret = req.body['client_secret']

    if( clientId && clientSecret ) {
      clientent.load$({appid:clientId,secret:clientSecret},function(err,client){
        if(err) return next(err);
        req.user = client
        next()
      })
    }
    else return next();
  };

  function info(req, res, next) {
    var access_token = req.query.access_token
    if( !access_token ) {
      access_token = req.headers.authorization
      if( access_token ) {
        access_token = access_token.substring('Bearer '.length)
      }
    }

    if( access_token ) {
      accesstokenent.load$(access_token,function(err,at){
      	if(err) return next(err);
      	if (at) {
          userent.load$(at.userID, function(err, user){
            if(user) {
              res.send({email:user.email, nick:user.nick, name:user.name, image:user.image, active:user.active, confirmed:user.confirmed})
            }
            else {
              res.send(400, "Invalid access token")
            }
          })
      	} else {
      		res.send(400, "Invalid access token")
      	}
      })
    }
    else res.send(400, "Missing access token")
  };

  app.use(buildClientContext);

  app.get('/dialog/authorize', oauth2srv.authorization);
  app.post('/dialog/authorize/decision', oauth2srv.decision);
  app.post('/oauth/token', oauth2srv.token);
  app.get('/api/v1/userinfo', info);

  return {
    buildClientContext: buildClientContext,
    info: info
  };

}<|endoftext|>


<commit_before>var stripANSI = require('strip-ansi');
var path = require('path');
var objectAssign = require('object-assign');
var os = require('os');
var notifier = require('node-notifier');

var DEFAULT_LOGO = path.join(__dirname, 'logo.png');

var WebpackNotifierPlugin = module.exports = function(options) {
    this.options = options || {};
    this.lastBuildSucceeded = false;
    this.isFirstBuild = true;
};

WebpackNotifierPlugin.prototype.compileMessage = function(stats) {
    function findFirstDFS(compilation, key) {
        var match = compilation[key][0];
        if (match) {
            return match;
        }

        var children = compilation.children;
        for (var i = 0; i < children.length; ++i) {
            match = findFirstDFS(children[i], key);
            if (match) {
                return match;
            }
        }
    }

    if (this.isFirstBuild) {
        this.isFirstBuild = false;

        if (this.options.skipFirstNotification) {
            return;
        }
    }

    var error;
    if (stats.hasErrors()) {
        error = findFirstDFS(stats.compilation, 'errors');

    } else if (stats.hasWarnings() && !this.options.excludeWarnings) {
        error = findFirstDFS(stats.compilation, 'warnings');

    } else if (!this.lastBuildSucceeded || this.options.alwaysNotify) {
        this.lastBuildSucceeded = true;
        return 'Build successful';

    } else {
        return;
    }

    this.lastBuildSucceeded = false;

    var message;
    if (error.module && error.module.rawRequest)
        message = error.module.rawRequest + '\n';

    if (error.error)
        message = 'Error: ' + message + error.error.toString();
    else if (error.warning)
        message = 'Warning: ' + message + error.warning.toString();
    else if (error.message) {
        message = 'Warning: ' + message + error.message.toString();
    }

    return stripANSI(message);
};

WebpackNotifierPlugin.prototype.compilationDone = function(stats) {
    var msg = this.compileMessage(stats);
    if (msg) {
        var contentImage = ('contentImage' in this.options) ?
            this.options.contentImage : DEFAULT_LOGO;

        notifier.notify(objectAssign({
            title: 'Webpack',
            message: msg,
            contentImage: contentImage,
            icon: (os.platform() === 'win32' || os.platform() === 'linux') ? contentImage : undefined
        }, this.options));
    }
};

WebpackNotifierPlugin.prototype.apply = function(compiler) {
  if (compiler.hooks) {
    var plugin = { name: 'Notifier' };

    compiler.hooks.done.tap(plugin, this.compilationDone.bind(this));
  } else {
    compiler.plugin('done', this.compilationDone.bind(this));
  }
};
<commit_msg>with --emoji icons<commit_after>var stripANSI = require('strip-ansi');
var path = require('path');
var objectAssign = require('object-assign');
var os = require('os');
var notifier = require('node-notifier');

var DEFAULT_LOGO = path.join(__dirname, 'logo.png');

var WebpackNotifierPlugin = module.exports = function(options) {
    this.options = options || {};
    this.lastBuildSucceeded = false;
    this.isFirstBuild = true;
};

WebpackNotifierPlugin.prototype.compileMessage = function(stats) {
    function findFirstDFS(compilation, key) {
        var match = compilation[key][0];
        if (match) {
            return match;
        }

        var children = compilation.children;
        for (var i = 0; i < children.length; ++i) {
            match = findFirstDFS(children[i], key);
            if (match) {
                return match;
            }
        }
    }

    if (this.isFirstBuild) {
        this.isFirstBuild = false;

        if (this.options.skipFirstNotification) {
            return;
        }
    }

    var error;
    if (stats.hasErrors()) {
        error = findFirstDFS(stats.compilation, 'errors');

    } else if (stats.hasWarnings() && !this.options.excludeWarnings) {
        error = findFirstDFS(stats.compilation, 'warnings');

    } else if (!this.lastBuildSucceeded || this.options.alwaysNotify) {
        this.lastBuildSucceeded = true;
        return (hasEmoji ? '✅ ' : '') + 'Build successful';

    } else {
        return;
    }

    this.lastBuildSucceeded = false;

    var message;
    if (error.module && error.module.rawRequest)
        message = error.module.rawRequest + '\n';

    var hasEmoji = this.options.emoji;
    if (error.error)
        message = (hasEmoji ? '❌ ' : '') + 'Error: ' + message + error.error.toString();
    else if (error.warning)
        message = (hasEmoji ? '⚠ ' : '') + 'Warning: ' + message + error.warning.toString();
    else if (error.message) {
        message = (hasEmoji ? '⚠ ' : '') + 'Warning: ' + message + error.message.toString();
    }

    return stripANSI(message);
};

WebpackNotifierPlugin.prototype.compilationDone = function(stats) {
    var msg = this.compileMessage(stats);
    if (msg) {
        var contentImage = ('contentImage' in this.options) ?
            this.options.contentImage : DEFAULT_LOGO;

        notifier.notify(objectAssign({
            title: 'Webpack',
            message: msg,
            contentImage: contentImage,
            icon: (os.platform() === 'win32' || os.platform() === 'linux') ? contentImage : undefined
        }, this.options));
    }
};

WebpackNotifierPlugin.prototype.apply = function(compiler) {
  if (compiler.hooks) {
    var plugin = { name: 'Notifier' };

    compiler.hooks.done.tap(plugin, this.compilationDone.bind(this));
  } else {
    compiler.plugin('done', this.compilationDone.bind(this));
  }
};
<|endoftext|>


<commit_before>/*
 Provides a set of services to build objects in a format that can
 be directly uploaded to Tidepool servers.

 Generally, call 'setDefaults' with the common fields you want to set default
 values for, then call a series of 'make' functions to build the base object,
 and then chain that to a series of 'with_' calls to set the fields. If you
 need to add a value that's not in the standard set of values for a given
 type, use the 'set' function.

 When complete, call the 'done' function, which removes the placeholders
 for optional fields and checks to make sure that required fields were
 supplied. The 'done' function returns the completed object.

 It looks like this:

 var cbg = builder.makeCBG()
 .with_value(data.glucose)
 .with_time(data.displayUtc)
 .with_deviceTime(data.displayTime)
 .set("trend", data.trendText)
 .done();

 */

/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var _ = require('lodash');
var util = require('util');

module.exports = function () {
  var REQUIRED = '**REQUIRED**';
  var OPTIONAL = '**OPTIONAL**';

  var deviceInfo = {
    time: REQUIRED,
    timezoneOffset: REQUIRED,
    clockDriftOffset: OPTIONAL,
    conversionOffset: REQUIRED,
    deviceTime: REQUIRED
  };
  function setDefaults(info) {
    deviceInfo = _.assign({}, deviceInfo, _.pick(info, 'deviceId', 'source', 'annotations'));
  }

  function _createObject() {
    return {
      // check to see if a field has been assigned or not
      isAssigned: function(k) {
        if (this[k] === OPTIONAL || this[k] === REQUIRED) {
          return false;
        }
        else if (this[k] != null) {
          return true;
        }
        else {
          return false;
        }
      },
      // use set to specify extra values that aren't in the template for
      // the data type
      set: function set(k, v) {
        if (v == null && this[k] && this[k] !== REQUIRED) {
          delete this[k];
        } else if (v != null) {
          this[k] = v;
        }
        return this;
      },

      // checks the object, removes unused optional fields,
      // and returns a copy of the object with all functions removed.
      done: function () {
        var self = this;

        var valid = _.reduce(this, function (result, value, key) {
          if (value === REQUIRED) {
            result.push(key);
          }
          return result;
        }, []);
        if (valid.length !== 0) {
          throw new Error(util.format('Some arguments to %s(%j) were not specified!', this.type, valid.join(',')));
        }

        // TODO: delete after conclusion of Jaeb study
        var payload;
        if (!_.isEmpty(self.jaebPayload)) {
          payload = self.payload === OPTIONAL ? {} : _.clone(self.payload);
          self.payload = _.assign({}, payload, self.jaebPayload);
          delete self.jaebPayload;
        }
        else if (self.index != null) {
          payload = self.payload === OPTIONAL ? {} : _.clone(self.payload);
          self.payload = _.assign({}, payload, {logIndices: [self.index]});
        /* NB: make sure to delete the index at the top level of each object
        / before uploading...unfortunately cannot do this here as some
        / Insulet objects get entirely built before the simulator, but
        / the simulator needs the index */
        }
        // TODO: end deletion

        return _.pickBy(this, function (value) {
          return !(_.isFunction(value) || value === OPTIONAL);
        });
      },

      _bindProps: function () {
        _.forIn(this, function (value, key, obj) {
          if (!_.isFunction(value)) {
            obj['with_' + key] = obj.set.bind(obj, key);
          }
        });
      }

    };
  }

  function makeAutomatedBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'automated',
      scheduleName: OPTIONAL,
      rate: REQUIRED,
      duration: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeBloodKetone() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bloodKetone',
      units: 'mmol/L',
      value: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeCBG() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'cbg',
      value: REQUIRED,
      units: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeCGMSettings() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'cgmSettings',
      transmitterId: REQUIRED,
      units: REQUIRED,
      displayUnits: OPTIONAL,
      lowAlerts: REQUIRED,
      highAlerts: REQUIRED,
      rateOfChangeAlerts: REQUIRED,
      outOfRangeAlerts: OPTIONAL,
      predictiveAlerts: OPTIONAL,
      calibrationAlerts: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventAlarm() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'alarm',
      alarmType: REQUIRED,
      status: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventCalibration() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'calibration',
      value: REQUIRED,
      units: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventReservoirChange() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'reservoirChange',
      status: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventPrime() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'prime',
      primeTarget: REQUIRED,
      volume: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventResume() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'status',
      status: 'resumed',
      reason: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventSuspend() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'status',
      status: 'suspended',
      reason: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventSuspendResume() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'status',
      status: 'suspended',
      reason: REQUIRED,
      duration: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventTimeChange() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'timeChange',
      change: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDualBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'dual/square',
      normal: REQUIRED,
      extended: REQUIRED,
      duration: REQUIRED,
      expectedNormal: OPTIONAL,
      expectedExtended: OPTIONAL,
      expectedDuration: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeFood() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'food',
      carbs: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeNormalBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'normal',
      normal: REQUIRED,
      payload: OPTIONAL,
      expectedNormal: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeNote() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'note',
      value: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makePumpSettings() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'pumpSettings',
      activeSchedule: REQUIRED,
      units: REQUIRED,
      basalSchedules: {},
      carbRatio: [],
      insulinSensitivity: [],
      bgTarget: [],
      bolus: OPTIONAL,
      basal: OPTIONAL,
      manufacturers: OPTIONAL,
      model: OPTIONAL,
      serialNumber: OPTIONAL,
      display: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    rec.add_basalScheduleItem = function (key, item) {
      if (!rec.basalSchedules[key]) {
        rec.basalSchedules[key] = [];
      }
      rec.basalSchedules[key].push(item);
    };
    rec.add_carbRatioItem = function (item) { rec.carbRatio.push(item); };
    rec.add_insulinSensitivityItem = function (item) { rec.insulinSensitivity.push(item); };
    rec.add_bgTargetItem = function (item) { rec.bgTarget.push(item); };
    return rec;
  }

  function makeTandemPumpSettings() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'pumpSettings',
      activeSchedule: REQUIRED,
      units: REQUIRED,
      basalSchedules: {},
      carbRatios: {},
      insulinSensitivities: {},
      bgTargets: {},
      insulin: OPTIONAL,
      bolus: OPTIONAL,
      manufacturers: OPTIONAL,
      model: OPTIONAL,
      serialNumber: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeScheduledBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'scheduled',
      scheduleName: OPTIONAL,
      rate: REQUIRED,
      duration: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeSMBG() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'smbg',
      value: REQUIRED,
      units: REQUIRED,
      subType: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeSquareBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'square',
      extended: REQUIRED,
      duration: REQUIRED,
      payload: OPTIONAL,
      expectedExtended: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeSuspendBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'suspend',
      duration: OPTIONAL,
      previous: OPTIONAL,
      suppressed: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeTempBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'temp',
      rate: OPTIONAL,
      percent: OPTIONAL,
      duration: REQUIRED,
      previous: OPTIONAL,
      suppressed: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeWizard() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'wizard',
      recommended: OPTIONAL,
      bgInput: OPTIONAL,
      carbInput: OPTIONAL,
      insulinOnBoard: OPTIONAL,
      insulinCarbRatio: OPTIONAL,
      insulinSensitivity: OPTIONAL,
      bgTarget: OPTIONAL,
      bolus: REQUIRED,
      units: REQUIRED,
      payload: OPTIONAL,
      carbUnits: OPTIONAL,
    });
    rec._bindProps();
    return rec;
  }

  function makeUpload() {
    var rec = _.assign(_createObject(), {
      type: 'upload',
      computerTime: REQUIRED,
      time: REQUIRED,
      timezoneOffset: REQUIRED,
      conversionOffset: REQUIRED,
      timezone: REQUIRED,
      timeProcessing: REQUIRED,
      version: REQUIRED,
      guid: OPTIONAL,
      uploadId: OPTIONAL,
      byUser: OPTIONAL,
      deviceTags: REQUIRED,
      deviceTime: OPTIONAL, // not all devices return current device time
      deviceManufacturers: REQUIRED,
      deviceModel: REQUIRED,
      deviceSerialNumber: OPTIONAL,
      deviceId: OPTIONAL,
      source: OPTIONAL, // for CareLink only
      payload: OPTIONAL,
      client: REQUIRED
    });
    rec._bindProps();
    return rec;
  }

  return {
    makeAutomatedBasal: makeAutomatedBasal,
    makeBloodKetone: makeBloodKetone,
    makeCBG: makeCBG,
    makeCGMSettings: makeCGMSettings,
    makeDeviceEventAlarm: makeDeviceEventAlarm,
    makeDeviceEventCalibration: makeDeviceEventCalibration,
    makeDeviceEventReservoirChange: makeDeviceEventReservoirChange,
    makeDeviceEventResume: makeDeviceEventResume,
    makeDeviceEventSuspend: makeDeviceEventSuspend,
    makeDeviceEventSuspendResume: makeDeviceEventSuspendResume,
    makeDeviceEventTimeChange: makeDeviceEventTimeChange,
    makeDeviceEventPrime: makeDeviceEventPrime,
    makeDualBolus: makeDualBolus,
    makeFood: makeFood,
    makeNormalBolus: makeNormalBolus,
    makeNote: makeNote,
    makePumpSettings: makePumpSettings,
    makeTandemPumpSettings: makeTandemPumpSettings,
    makeScheduledBasal: makeScheduledBasal,
    makeSMBG: makeSMBG,
    makeSquareBolus: makeSquareBolus,
    makeSuspendBasal: makeSuspendBasal,
    makeTempBasal: makeTempBasal,
    makeUpload: makeUpload,
    makeWizard: makeWizard,
    setDefaults: setDefaults
  };
};
<commit_msg>add automated bolus to objectBuilder<commit_after>/*
 Provides a set of services to build objects in a format that can
 be directly uploaded to Tidepool servers.

 Generally, call 'setDefaults' with the common fields you want to set default
 values for, then call a series of 'make' functions to build the base object,
 and then chain that to a series of 'with_' calls to set the fields. If you
 need to add a value that's not in the standard set of values for a given
 type, use the 'set' function.

 When complete, call the 'done' function, which removes the placeholders
 for optional fields and checks to make sure that required fields were
 supplied. The 'done' function returns the completed object.

 It looks like this:

 var cbg = builder.makeCBG()
 .with_value(data.glucose)
 .with_time(data.displayUtc)
 .with_deviceTime(data.displayTime)
 .set("trend", data.trendText)
 .done();

 */

/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var _ = require('lodash');
var util = require('util');

module.exports = function () {
  var REQUIRED = '**REQUIRED**';
  var OPTIONAL = '**OPTIONAL**';

  var deviceInfo = {
    time: REQUIRED,
    timezoneOffset: REQUIRED,
    clockDriftOffset: OPTIONAL,
    conversionOffset: REQUIRED,
    deviceTime: REQUIRED
  };
  function setDefaults(info) {
    deviceInfo = _.assign({}, deviceInfo, _.pick(info, 'deviceId', 'source', 'annotations'));
  }

  function _createObject() {
    return {
      // check to see if a field has been assigned or not
      isAssigned: function(k) {
        if (this[k] === OPTIONAL || this[k] === REQUIRED) {
          return false;
        }
        else if (this[k] != null) {
          return true;
        }
        else {
          return false;
        }
      },
      // use set to specify extra values that aren't in the template for
      // the data type
      set: function set(k, v) {
        if (v == null && this[k] && this[k] !== REQUIRED) {
          delete this[k];
        } else if (v != null) {
          this[k] = v;
        }
        return this;
      },

      // checks the object, removes unused optional fields,
      // and returns a copy of the object with all functions removed.
      done: function () {
        var self = this;

        var valid = _.reduce(this, function (result, value, key) {
          if (value === REQUIRED) {
            result.push(key);
          }
          return result;
        }, []);
        if (valid.length !== 0) {
          throw new Error(util.format('Some arguments to %s(%j) were not specified!', this.type, valid.join(',')));
        }

        // TODO: delete after conclusion of Jaeb study
        var payload;
        if (!_.isEmpty(self.jaebPayload)) {
          payload = self.payload === OPTIONAL ? {} : _.clone(self.payload);
          self.payload = _.assign({}, payload, self.jaebPayload);
          delete self.jaebPayload;
        }
        else if (self.index != null) {
          payload = self.payload === OPTIONAL ? {} : _.clone(self.payload);
          self.payload = _.assign({}, payload, {logIndices: [self.index]});
        /* NB: make sure to delete the index at the top level of each object
        / before uploading...unfortunately cannot do this here as some
        / Insulet objects get entirely built before the simulator, but
        / the simulator needs the index */
        }
        // TODO: end deletion

        return _.pickBy(this, function (value) {
          return !(_.isFunction(value) || value === OPTIONAL);
        });
      },

      _bindProps: function () {
        _.forIn(this, function (value, key, obj) {
          if (!_.isFunction(value)) {
            obj['with_' + key] = obj.set.bind(obj, key);
          }
        });
      }

    };
  }

  function makeAutomatedBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'automated',
      scheduleName: OPTIONAL,
      rate: REQUIRED,
      duration: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeBloodKetone() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bloodKetone',
      units: 'mmol/L',
      value: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeCBG() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'cbg',
      value: REQUIRED,
      units: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeCGMSettings() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'cgmSettings',
      transmitterId: REQUIRED,
      units: REQUIRED,
      displayUnits: OPTIONAL,
      lowAlerts: REQUIRED,
      highAlerts: REQUIRED,
      rateOfChangeAlerts: REQUIRED,
      outOfRangeAlerts: OPTIONAL,
      predictiveAlerts: OPTIONAL,
      calibrationAlerts: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventAlarm() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'alarm',
      alarmType: REQUIRED,
      status: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventCalibration() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'calibration',
      value: REQUIRED,
      units: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventReservoirChange() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'reservoirChange',
      status: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventPrime() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'prime',
      primeTarget: REQUIRED,
      volume: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventResume() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'status',
      status: 'resumed',
      reason: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventSuspend() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'status',
      status: 'suspended',
      reason: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventSuspendResume() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'status',
      status: 'suspended',
      reason: REQUIRED,
      duration: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDeviceEventTimeChange() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'deviceEvent',
      subType: 'timeChange',
      change: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeDualBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'dual/square',
      normal: REQUIRED,
      extended: REQUIRED,
      duration: REQUIRED,
      expectedNormal: OPTIONAL,
      expectedExtended: OPTIONAL,
      expectedDuration: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeFood() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'food',
      carbs: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeNormalBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'normal',
      normal: REQUIRED,
      payload: OPTIONAL,
      expectedNormal: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeAutomatedBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'automated',
      normal: REQUIRED,
      payload: OPTIONAL,
      expectedNormal: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeNote() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'note',
      value: REQUIRED,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makePumpSettings() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'pumpSettings',
      activeSchedule: REQUIRED,
      units: REQUIRED,
      basalSchedules: {},
      carbRatio: [],
      insulinSensitivity: [],
      bgTarget: [],
      bolus: OPTIONAL,
      basal: OPTIONAL,
      manufacturers: OPTIONAL,
      model: OPTIONAL,
      serialNumber: OPTIONAL,
      display: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    rec.add_basalScheduleItem = function (key, item) {
      if (!rec.basalSchedules[key]) {
        rec.basalSchedules[key] = [];
      }
      rec.basalSchedules[key].push(item);
    };
    rec.add_carbRatioItem = function (item) { rec.carbRatio.push(item); };
    rec.add_insulinSensitivityItem = function (item) { rec.insulinSensitivity.push(item); };
    rec.add_bgTargetItem = function (item) { rec.bgTarget.push(item); };
    return rec;
  }

  function makeTandemPumpSettings() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'pumpSettings',
      activeSchedule: REQUIRED,
      units: REQUIRED,
      basalSchedules: {},
      carbRatios: {},
      insulinSensitivities: {},
      bgTargets: {},
      insulin: OPTIONAL,
      bolus: OPTIONAL,
      manufacturers: OPTIONAL,
      model: OPTIONAL,
      serialNumber: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeScheduledBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'scheduled',
      scheduleName: OPTIONAL,
      rate: REQUIRED,
      duration: REQUIRED,
      previous: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeSMBG() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'smbg',
      value: REQUIRED,
      units: REQUIRED,
      subType: OPTIONAL,
      payload: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeSquareBolus() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'bolus',
      subType: 'square',
      extended: REQUIRED,
      duration: REQUIRED,
      payload: OPTIONAL,
      expectedExtended: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeSuspendBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'suspend',
      duration: OPTIONAL,
      previous: OPTIONAL,
      suppressed: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeTempBasal() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'basal',
      deliveryType: 'temp',
      rate: OPTIONAL,
      percent: OPTIONAL,
      duration: REQUIRED,
      previous: OPTIONAL,
      suppressed: OPTIONAL,
      payload: OPTIONAL,
      expectedDuration: OPTIONAL
    });
    rec._bindProps();
    return rec;
  }

  function makeWizard() {
    var rec = _.assign(_createObject(), deviceInfo, {
      type: 'wizard',
      recommended: OPTIONAL,
      bgInput: OPTIONAL,
      carbInput: OPTIONAL,
      insulinOnBoard: OPTIONAL,
      insulinCarbRatio: OPTIONAL,
      insulinSensitivity: OPTIONAL,
      bgTarget: OPTIONAL,
      bolus: REQUIRED,
      units: REQUIRED,
      payload: OPTIONAL,
      carbUnits: OPTIONAL,
    });
    rec._bindProps();
    return rec;
  }

  function makeUpload() {
    var rec = _.assign(_createObject(), {
      type: 'upload',
      computerTime: REQUIRED,
      time: REQUIRED,
      timezoneOffset: REQUIRED,
      conversionOffset: REQUIRED,
      timezone: REQUIRED,
      timeProcessing: REQUIRED,
      version: REQUIRED,
      guid: OPTIONAL,
      uploadId: OPTIONAL,
      byUser: OPTIONAL,
      deviceTags: REQUIRED,
      deviceTime: OPTIONAL, // not all devices return current device time
      deviceManufacturers: REQUIRED,
      deviceModel: REQUIRED,
      deviceSerialNumber: OPTIONAL,
      deviceId: OPTIONAL,
      source: OPTIONAL, // for CareLink only
      payload: OPTIONAL,
      client: REQUIRED
    });
    rec._bindProps();
    return rec;
  }

  return {
    makeAutomatedBasal: makeAutomatedBasal,
    makeAutomatedBolus: makeAutomatedBolus,
    makeBloodKetone: makeBloodKetone,
    makeCBG: makeCBG,
    makeCGMSettings: makeCGMSettings,
    makeDeviceEventAlarm: makeDeviceEventAlarm,
    makeDeviceEventCalibration: makeDeviceEventCalibration,
    makeDeviceEventReservoirChange: makeDeviceEventReservoirChange,
    makeDeviceEventResume: makeDeviceEventResume,
    makeDeviceEventSuspend: makeDeviceEventSuspend,
    makeDeviceEventSuspendResume: makeDeviceEventSuspendResume,
    makeDeviceEventTimeChange: makeDeviceEventTimeChange,
    makeDeviceEventPrime: makeDeviceEventPrime,
    makeDualBolus: makeDualBolus,
    makeFood: makeFood,
    makeNormalBolus: makeNormalBolus,
    makeNote: makeNote,
    makePumpSettings: makePumpSettings,
    makeTandemPumpSettings: makeTandemPumpSettings,
    makeScheduledBasal: makeScheduledBasal,
    makeSMBG: makeSMBG,
    makeSquareBolus: makeSquareBolus,
    makeSuspendBasal: makeSuspendBasal,
    makeTempBasal: makeTempBasal,
    makeUpload: makeUpload,
    makeWizard: makeWizard,
    setDefaults: setDefaults
  };
};
<|endoftext|>


<commit_before>'use strict';

var RSVP = require('rsvp');
var path = require('path');
var mkdirp = require('mkdirp');
var webpack = require('webpack');
var Plugin = require('broccoli-plugin');
var symlinkOrCopySync = require('symlink-or-copy').sync;

var PreventResolveSymlinkPlugin = require('./prevent-resolve-symlink-plugin');

function WebpackFilter(inputNode, options) {
  if (!(this instanceof WebpackFilter)) return new WebpackFilter(inputNode, options);

  if (Array.isArray(inputNode)) {
    throw new Error("WebpackFilter only accepts a single inputNode");
  }

  Plugin.call(this, [inputNode], {
    annotation: options.annotation
  });
  this.options = options;
}

WebpackFilter.prototype = Object.create(Plugin.prototype);
WebpackFilter.prototype.constructor = WebpackFilter;

WebpackFilter.prototype.initializeCompiler = function() {
  if (this.options.context) throw new Error("WebpackFilter will set the webpack context, you shouldn't set it.");
  if (this.options.cache) throw new Error("WebpackFilter will set the webpack cache, you shouldn't set it.");
  if (this.options.output && this.options.output.path) throw new Error("WebpackFilter will set the webpack output.path, you shouldn't set it.");

  this.options.context = this.inputPaths[0];
  this.options.output = this.options.output || {};
  this.options.output.path = this.cachePath;

  // Let webpack do all the caching (we will call webpack's compile method every
  // build and rely on it to only build what is necessary)
  this.options.cache = this._webpackCache = {};

  // Prevent Webpack's ResultSymlinkPlugin from breaking relative paths in symlinked
  // modules (a common problem with Broccoli's highly symlinked output trees).
  // This is on by default, but can be disabled.
  if (this.options.preventSymlinkResolution === true || this.options.preventSymlinkResolution === undefined)  {
    this.options.plugins = this.options.plugins || [];
    this.options.plugins.push(
      new webpack.ResolverPlugin([PreventResolveSymlinkPlugin])
    );
  }

  return webpack(this.options);
}

WebpackFilter.prototype.build = function() {
  if (this.compiler === undefined) {
    this.compiler = this.initializeCompiler();
  }

  var that = this;

  return new RSVP.Promise(function(resolve, reject) {
    that.compiler.run(function(err, stats) {
      var jsonStats = stats.toJson();
      if (jsonStats.errors.length > 0) jsonStats.errors.forEach(console.error);
      if (jsonStats.warnings.length > 0) jsonStats.warnings.forEach(console.warn);
      if (err || jsonStats.errors.length > 0) {
        reject(err);
      } else {
        // Get all of the assets from webpack, both emitted in this current compile
        // pass and not emitted (aka, cached). And then symlink all of them from the
        // cache folder (where webpack writes) to the output folder
        jsonStats.assets.map(function(asset) {
          mkdirp.sync(path.dirname(that.outputPath + '/' + asset.name));
          symlinkOrCopySync(that.cachePath + '/' + asset.name, that.outputPath + '/' + asset.name);
        });

        resolve();
      }
    });
  });
};

module.exports = WebpackFilter;
<commit_msg>Log webpack output by default, but allow overriding<commit_after>'use strict';

var RSVP = require('rsvp');
var path = require('path');
var mkdirp = require('mkdirp');
var webpack = require('webpack');
var Plugin = require('broccoli-plugin');
var symlinkOrCopySync = require('symlink-or-copy').sync;

var PreventResolveSymlinkPlugin = require('./prevent-resolve-symlink-plugin');

function WebpackFilter(inputNode, options) {
  if (!(this instanceof WebpackFilter)) return new WebpackFilter(inputNode, options);

  if (Array.isArray(inputNode)) {
    throw new Error("WebpackFilter only accepts a single inputNode");
  }

  Plugin.call(this, [inputNode], {
    annotation: options.annotation
  });
  this.options = options;
}

WebpackFilter.prototype = Object.create(Plugin.prototype);
WebpackFilter.prototype.constructor = WebpackFilter;

WebpackFilter.prototype.initializeCompiler = function() {
  if (this.options.context) throw new Error("WebpackFilter will set the webpack context, you shouldn't set it.");
  if (this.options.cache) throw new Error("WebpackFilter will set the webpack cache, you shouldn't set it.");
  if (this.options.output && this.options.output.path) throw new Error("WebpackFilter will set the webpack output.path, you shouldn't set it.");

  this.options.context = this.inputPaths[0];
  this.options.output = this.options.output || {};
  this.options.output.path = this.cachePath;

  // Let webpack do all the caching (we will call webpack's compile method every
  // build and rely on it to only build what is necessary)
  this.options.cache = this._webpackCache = {};

  // By default, log webpack's output to the console
  this.options.logStats = this.options.logStats || true;

  // Prevent Webpack's ResultSymlinkPlugin from breaking relative paths in symlinked
  // modules (a common problem with Broccoli's highly symlinked output trees).
  // This is on by default, but can be disabled.
  if (this.options.preventSymlinkResolution === true || this.options.preventSymlinkResolution === undefined)  {
    this.options.plugins = this.options.plugins || [];
    this.options.plugins.push(
      new webpack.ResolverPlugin([PreventResolveSymlinkPlugin])
    );
  }

  return webpack(this.options);
}

WebpackFilter.prototype.build = function() {
  if (this.compiler === undefined) {
    this.compiler = this.initializeCompiler();
  }

  var that = this;

  return new RSVP.Promise(function(resolve, reject) {
    that.compiler.run(function(err, stats) {
      var jsonStats = stats.toJson();

      if (that.options.logStats) {
        var loggingOptions;

        // Allow options.logStats to be a string or object that is passed to
        // stats.toString(). More info in:
        //   - http://webpack.github.io/docs/node.js-api.html#stats-tostring
        //   - https://github.com/webpack/webpack/pull/1323
        if (that.options.logStats === true) {
          loggingOptions = 'verbose';
        } else {
          loggingOptions = that.options.logStats;
        }

        console.log("\n[webpack]", stats.toString(loggingOptions));
      }

      if (jsonStats.errors.length > 0) jsonStats.errors.forEach(console.error);
      if (jsonStats.warnings.length > 0) jsonStats.warnings.forEach(console.warn);
      if (err || jsonStats.errors.length > 0) {
        reject(err);
      } else {
        // Get all of the assets from webpack, both emitted in this current compile
        // pass and not emitted (aka, cached). And then symlink all of them from the
        // cache folder (where webpack writes) to the output folder
        jsonStats.assets.map(function(asset) {
          mkdirp.sync(path.dirname(that.outputPath + '/' + asset.name));
          symlinkOrCopySync(that.cachePath + '/' + asset.name, that.outputPath + '/' + asset.name);
        });

        resolve();
      }
    });
  });
};

module.exports = WebpackFilter;
<|endoftext|>


<commit_before>var singularRules  = [],
    pluralizeRules = [],
    // Using objects for fast lookups
    uncountables   = {},
    irregular      = {},
    sanitizeWord, sanitizeRule,
    restoreCase,
    pluralize,
    plural, singular;

sanitizeRule = function (rule) {
  if (typeof rule === 'string') {
    return new RegExp('^' + rule + '$', 'i');
  }
  return rule;
};

restoreCase = function (token) {
  // All capital letters
  if (token === token.toUpperCase()) {
    return function (word) {
      return word.toUpperCase();
    };
  }
  // Title cased word
  if (token[0] === token[0].toUpperCase()) {
    return function (word) {
      return word[0].toUpperCase() + word.substr(1);
    };
  }

  return function (word) {
    return word.toLowerCase();
  };
};

// Conveniently, the word will always lowercased when passes in here
sanitizeWord = function (word, collection) {
  if (word.length < 2) { return word; } // Empty string or no word to fix

  var found, match;
  if (typeof uncountables[word] === 'undefined') {
    found = collection.some(function (rule) {
      match = rule;
      return word.match(rule[0]);
    });
    if (found) {
      return word.replace(match[0], match[1]);
    }
  }
  return word;
};

pluralize = module.exports = function (word, count, inclusive) {
  count = +count || 0; // If the numbered count is falsy, use `0`

  return (inclusive ? count + ' ' : '') + (count === 1 ? singular(word) : plural(word));
};

plural = pluralize.plural = function (word) {
  var restoreWord = restoreCase(word);
  word            = word.trim().toLowerCase();

  if (irregular[word]) { return restoreWord(irregular[word]); }

  var found;
  Object.keys(irregular).some(function (singular) {
    if (irregular[singular] === word) {
      return found = word;
    }
  });
  if (found) { return restoreWord(found); }

  return restoreWord(sanitizeWord(word, pluralizeRules));
};

singular = pluralize.singular = function (word) {
  var restoreWord = restoreCase(word);
  word            = word.trim().toLowerCase();

  if (irregular[word]) { return restoreWord(word); }

  var found;
  Object.keys(irregular).some(function (singular) {
    if (irregular[singular] === word) {
      return found = singular;
    }
  });
  if (found) { return restoreWord(found); }

  return restoreWord(sanitizeWord(word, singularRules));
};

pluralize.addPluralRule = function (rule, replacement) {
  pluralizeRules.unshift([ sanitizeRule(rule), replacement ]);
};

pluralize.addSingularRule = function (rule, replacement) {
  singularRules.unshift([ sanitizeRule(rule), replacement ]);
};

pluralize.addUncountableRule = function (word) {
  if (typeof word === 'string') {
    return uncountables[word.toLowerCase()] = true;
  }

  // Set singular and plural references for the word
  pluralize.addPluralRule(word, '$&');
  pluralize.addSingularRule(word, '$&');
};

pluralize.addIrregularRule = function (singular, plural) {
  irregular[singular] = plural; // Hashed pattern for faster lookup
};

// Pronouns
pluralize.addIrregularRule('i', 'we');
pluralize.addIrregularRule('me', 'us');
pluralize.addIrregularRule('he', 'they');
pluralize.addIrregularRule('she', 'they');
pluralize.addIrregularRule('them', 'them');
pluralize.addIrregularRule('myself', 'ourselves');
pluralize.addIrregularRule('yourself', 'yourselves');
pluralize.addIrregularRule('itself', 'themselves');
pluralize.addIrregularRule('herself', 'themselves');
pluralize.addIrregularRule('himself', 'themselves');
pluralize.addIrregularRule('themself', 'themselves');
// Words ending in with a consonant and `o`
pluralize.addIrregularRule('canto', 'cantos');
pluralize.addIrregularRule('hetero', 'heteros');
pluralize.addIrregularRule('photo', 'photos');
pluralize.addIrregularRule('zero', 'zeros');
pluralize.addIrregularRule('piano', 'pianos');
pluralize.addIrregularRule('portico', 'porticos');
pluralize.addIrregularRule('pro', 'pros');
pluralize.addIrregularRule('quarto', 'quartos');
pluralize.addIrregularRule('kimono', 'kimonos');
// Anything else
pluralize.addIrregularRule('ox', 'oxen');
pluralize.addIrregularRule('die', 'dice');
pluralize.addIrregularRule('foot', 'feet');
pluralize.addIrregularRule('goose', 'geese');
pluralize.addIrregularRule('quiz', 'quizzes');
pluralize.addIrregularRule('human', 'humans');
pluralize.addIrregularRule('proof', 'proofs');
pluralize.addIrregularRule('carve', 'carves');
pluralize.addIrregularRule('valve', 'valves');
pluralize.addIrregularRule('thief', 'thieves');
pluralize.addIrregularRule('groove', 'grooves');
pluralize.addIrregularRule('stigma', 'stigmata');
// Ends with `us`
pluralize.addIrregularRule('genus', 'genera');
pluralize.addIrregularRule('viscus', 'viscera');
pluralize.addIrregularRule('syllabus', 'syllabi');

pluralize.addPluralRule(/$/, 's');
pluralize.addPluralRule(/s$/, 's');
pluralize.addPluralRule(/(ese)$/, '$1');
pluralize.addPluralRule(/^(ax|test)is$/, '$1es');
pluralize.addPluralRule(/([au]s)$/, '$1es');
pluralize.addPluralRule(/(e[mn]u)s?$/, '$1s');
pluralize.addPluralRule(/([^l]ias|[aeiou]las|[emjzr]as)$/, '$1');
pluralize.addPluralRule(/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc)(us|i)$/, '$1i');
pluralize.addPluralRule(/^(alumn|alg|vertebr)(a|ae)$/, '$1ae');
pluralize.addPluralRule(/(bu)s$/, '$1ses');
pluralize.addPluralRule(/([^aeiou])o$/, '$1oes');
pluralize.addPluralRule(/^(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi)(a|um)$/, '$1a');
pluralize.addPluralRule(/^(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|\w+hedr)(a|on)$/, '$1a');
pluralize.addPluralRule(/sis$/, 'ses');
pluralize.addPluralRule(/(?:([^f])fe|(ar|l|[eo][ao])f)$/, '$1$2ves');
pluralize.addPluralRule(/([^aeiouy]|qu)y$/, '$1ies');
pluralize.addPluralRule(/(x|ch|ss|sh|zz)$/, '$1es');
pluralize.addPluralRule(/(matr|cod|mur|sil|vert|ind)(ix|ex)$/, '$1ices');
pluralize.addPluralRule(/^(m|l)(ice|ouse)$/, '$1ice');
pluralize.addPluralRule(/(pe)(rson|ople)$/, '$1ople');
pluralize.addPluralRule(/(child)(ren)?$/, '$1ren');
pluralize.addPluralRule(/(eau)x?$/, '$1x');
pluralize.addPluralRule(/m(a|e)n$/, 'men');

pluralize.addSingularRule(/s$/, '');
pluralize.addSingularRule(/(ss)$/, '$1');
pluralize.addSingularRule(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/, '$1sis');
pluralize.addSingularRule(/(^analy)(sis|ses)$/, '$1sis');
pluralize.addSingularRule(/([^afor])ves$/, '$1fe');
pluralize.addSingularRule(/(hive|tive|dr?ive)s$/, '$1');
pluralize.addSingularRule(/(ar|l|[eo][ao])ves$/, '$1f');
pluralize.addSingularRule(/([^aeiouy]|qu)ies$/, '$1y');
pluralize.addSingularRule(/(^[pl]ie|tie|zombie)s$/, '$1');
pluralize.addSingularRule(/(x|ch|ss|sh|zz)es$/, '$1');
pluralize.addSingularRule(/^(m|l)ice$/, '$1ouse');
pluralize.addSingularRule(/(bus|alias|[mpst]us|atlas|gas)(es)?$/, '$1');
pluralize.addSingularRule(/(e[mn]u)s?$/, '$1');
pluralize.addSingularRule(/(o)es$/, '$1');
pluralize.addSingularRule(/^(canoe)s$/, '$1');
pluralize.addSingularRule(/(shoe|movie|move)s$/, '$1');
pluralize.addSingularRule(/(cris|test|diagnos)(is|es)$/, '$1is');
pluralize.addSingularRule(/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc)(us|i)$/, '$1us');
pluralize.addSingularRule(/^(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi)a$/, '$1um');
pluralize.addSingularRule(/^(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|\w+hedr)a$/, '$1on');
pluralize.addSingularRule(/^(alumn|alg|vertebr)ae$/, '$1a');
pluralize.addSingularRule(/(cod|mur|sil|vert|ind)ices$/, '$1ex');
pluralize.addSingularRule(/(matr)ices$/, '$1ix');
pluralize.addSingularRule(/(pe)(rson|ople)$/, '$1rson');
pluralize.addSingularRule(/(child)ren$/, '$1');
pluralize.addSingularRule(/(eau)x$/, '$1');
pluralize.addSingularRule(/men$/, 'man');

// http://en.wikipedia.org/wiki/English_plural#Singulars_without_plurals
[
'advice', 'agenda', 'bison', 'bream', 'buffalo', 'carp', 'chassis',
'cod', 'cooperation', 'corps', 'digestion', 'debris', 'diabetes',
'energy', 'equipment', 'elk', 'excretion', 'expertise', 'flounder',
'gallows', 'graffiti', 'headquarters', 'health', 'herpes', 'highjinks',
'homework', 'information', 'jeans', 'justice', 'labour', 'machinery',
'mackerel', 'media', 'mews', 'money', 'moose', 'news', 'pike', 'plankton',
'pliers', 'pollution', 'rain', 'rice', 'salmon', 'scissors', 'series',
'sewage', 'shrimp', 'species', 'staff', 'swine', 'trout', 'tuna',
'whiting', 'wildebeest'
].forEach(pluralize.addUncountableRule);

// Uncountable regexes
pluralize.addUncountableRule(/pox$/);
pluralize.addUncountableRule(/ois$/);
pluralize.addUncountableRule(/deer$/);
pluralize.addUncountableRule(/fish$/);
pluralize.addUncountableRule(/sheep$/);
pluralize.addUncountableRule(/measles$/);
pluralize.addUncountableRule(/[nrlm]ese$/);
<commit_msg>Added more irregulars<commit_after>var singularRules  = [],
    pluralizeRules = [],
    // Using objects for fast lookups
    uncountables   = {},
    irregular      = {},
    sanitizeWord, sanitizeRule,
    restoreCase,
    pluralize,
    plural, singular;

sanitizeRule = function (rule) {
  if (typeof rule === 'string') {
    return new RegExp('^' + rule + '$', 'i');
  }
  return rule;
};

restoreCase = function (token) {
  // All capital letters
  if (token === token.toUpperCase()) {
    return function (word) {
      return word.toUpperCase();
    };
  }
  // Title cased word
  if (token[0] === token[0].toUpperCase()) {
    return function (word) {
      return word[0].toUpperCase() + word.substr(1);
    };
  }

  return function (word) {
    return word.toLowerCase();
  };
};

// Conveniently, the word will always lowercased when passes in here
sanitizeWord = function (word, collection) {
  if (word.length < 2) { return word; } // Empty string or no word to fix

  var found, match;
  if (typeof uncountables[word] === 'undefined') {
    found = collection.some(function (rule) {
      match = rule;
      return word.match(rule[0]);
    });
    if (found) {
      return word.replace(match[0], match[1]);
    }
  }
  return word;
};

pluralize = module.exports = function (word, count, inclusive) {
  count = +count || 0; // If the numbered count is falsy, use `0`

  return (inclusive ? count + ' ' : '') + (count === 1 ? singular(word) : plural(word));
};

plural = pluralize.plural = function (word) {
  var restoreWord = restoreCase(word);
  word            = word.trim().toLowerCase();

  if (irregular[word]) { return restoreWord(irregular[word]); }

  var found;
  Object.keys(irregular).some(function (singular) {
    if (irregular[singular] === word) {
      return found = word;
    }
  });
  if (found) { return restoreWord(found); }

  return restoreWord(sanitizeWord(word, pluralizeRules));
};

singular = pluralize.singular = function (word) {
  var restoreWord = restoreCase(word);
  word            = word.trim().toLowerCase();

  if (irregular[word]) { return restoreWord(word); }

  var found;
  Object.keys(irregular).some(function (singular) {
    if (irregular[singular] === word) {
      return found = singular;
    }
  });
  if (found) { return restoreWord(found); }

  return restoreWord(sanitizeWord(word, singularRules));
};

pluralize.addPluralRule = function (rule, replacement) {
  pluralizeRules.unshift([ sanitizeRule(rule), replacement ]);
};

pluralize.addSingularRule = function (rule, replacement) {
  singularRules.unshift([ sanitizeRule(rule), replacement ]);
};

pluralize.addUncountableRule = function (word) {
  if (typeof word === 'string') {
    return uncountables[word.toLowerCase()] = true;
  }

  // Set singular and plural references for the word
  pluralize.addPluralRule(word, '$&');
  pluralize.addSingularRule(word, '$&');
};

pluralize.addIrregularRule = function (singular, plural) {
  irregular[singular] = plural; // Hashed pattern for faster lookup
};

// Pronouns
pluralize.addIrregularRule('i', 'we');
pluralize.addIrregularRule('me', 'us');
pluralize.addIrregularRule('he', 'they');
pluralize.addIrregularRule('she', 'they');
pluralize.addIrregularRule('them', 'them');
pluralize.addIrregularRule('myself', 'ourselves');
pluralize.addIrregularRule('yourself', 'yourselves');
pluralize.addIrregularRule('itself', 'themselves');
pluralize.addIrregularRule('herself', 'themselves');
pluralize.addIrregularRule('himself', 'themselves');
pluralize.addIrregularRule('themself', 'themselves');
// Words ending in with a consonant and `o`
pluralize.addIrregularRule('canto', 'cantos');
pluralize.addIrregularRule('hetero', 'heteros');
pluralize.addIrregularRule('photo', 'photos');
pluralize.addIrregularRule('zero', 'zeros');
pluralize.addIrregularRule('piano', 'pianos');
pluralize.addIrregularRule('portico', 'porticos');
pluralize.addIrregularRule('pro', 'pros');
pluralize.addIrregularRule('quarto', 'quartos');
pluralize.addIrregularRule('kimono', 'kimonos');
// Anything else
pluralize.addIrregularRule('ox', 'oxen');
pluralize.addIrregularRule('die', 'dice');
pluralize.addIrregularRule('foot', 'feet');
pluralize.addIrregularRule('goose', 'geese');
pluralize.addIrregularRule('quiz', 'quizzes');
pluralize.addIrregularRule('human', 'humans');
pluralize.addIrregularRule('proof', 'proofs');
pluralize.addIrregularRule('carve', 'carves');
pluralize.addIrregularRule('valve', 'valves');
pluralize.addIrregularRule('thief', 'thieves');
pluralize.addIrregularRule('groove', 'grooves');
// Greek-Originated -mata words
pluralize.addIrregularRule('stigma', 'stigmata');
pluralize.addIrregularRule('stoma', 'stomata');
pluralize.addIrregularRule('dogma', 'dogmata');
pluralize.addIrregularRule('lemma', 'lemmata');
pluralize.addIrregularRule('schema', 'schemata'); // Technically Correct
pluralize.addIrregularRule('anathema', 'anathemata');
// Ends with `us`
pluralize.addIrregularRule('genus', 'genera');
pluralize.addIrregularRule('viscus', 'viscera');
pluralize.addIrregularRule('syllabus', 'syllabi');
pluralize.addIrregularRule('uterus', 'uteri');
// Latin 2nd Declension Neuter-Originated English Words
pluralize.addIrregularRule('referendum', 'referenda');
pluralize.addIrregularRule('datum', 'data');
pluralize.addIrregularRule('bacterium', 'bacteria');
pluralize.addIrregularRule('curriculum', 'curricula');
pluralize.addIrregularRule('ovum', 'ova');
pluralize.addIrregularRule('automatum', 'automata');
// Latin 3rd Decelnsion Neuter-Originated English Words
pluralize.addIrregularRule('phenomenon', 'phenomena');
pluralize.addIrregularRule('criterion', 'criteria');
pluralize.addIrregularRule('polyhedron', 'polyhedra');

pluralize.addPluralRule(/$/, 's');
pluralize.addPluralRule(/s$/, 's');
pluralize.addPluralRule(/(ese)$/, '$1');
pluralize.addPluralRule(/^(ax|test)is$/, '$1es');
pluralize.addPluralRule(/([au]s)$/, '$1es');
pluralize.addPluralRule(/(e[mn]u)s?$/, '$1s');
pluralize.addPluralRule(/([^l]ias|[aeiou]las|[emjzr]as)$/, '$1');
pluralize.addPluralRule(/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc)(us|i)$/, '$1i');
pluralize.addPluralRule(/^(alumn|alg|vertebr)(a|ae)$/, '$1ae');
pluralize.addPluralRule(/(bu)s$/, '$1ses');
pluralize.addPluralRule(/([^aeiou])o$/, '$1oes');
pluralize.addPluralRule(/^(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi)(a|um)$/, '$1a');
pluralize.addPluralRule(/^(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|\w+hedr)(a|on)$/, '$1a');
pluralize.addPluralRule(/sis$/, 'ses');
pluralize.addPluralRule(/(?:([^f])fe|(ar|l|[eo][ao])f)$/, '$1$2ves');
pluralize.addPluralRule(/([^aeiouy]|qu)y$/, '$1ies');
pluralize.addPluralRule(/(x|ch|ss|sh|zz)$/, '$1es');
pluralize.addPluralRule(/(matr|cod|mur|sil|vert|ind)(ix|ex)$/, '$1ices');
pluralize.addPluralRule(/^(m|l)(ice|ouse)$/, '$1ice');
pluralize.addPluralRule(/(pe)(rson|ople)$/, '$1ople');
pluralize.addPluralRule(/(child)(ren)?$/, '$1ren');
pluralize.addPluralRule(/(eau)x?$/, '$1x');
pluralize.addPluralRule(/m(a|e)n$/, 'men');

pluralize.addSingularRule(/s$/, '');
pluralize.addSingularRule(/(ss)$/, '$1');
pluralize.addSingularRule(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/, '$1sis');
pluralize.addSingularRule(/(^analy)(sis|ses)$/, '$1sis');
pluralize.addSingularRule(/([^afor])ves$/, '$1fe');
pluralize.addSingularRule(/(hive|tive|dr?ive)s$/, '$1');
pluralize.addSingularRule(/(ar|l|[eo][ao])ves$/, '$1f');
pluralize.addSingularRule(/([^aeiouy]|qu)ies$/, '$1y');
pluralize.addSingularRule(/(^[pl]ie|tie|zombie)s$/, '$1');
pluralize.addSingularRule(/(x|ch|ss|sh|zz)es$/, '$1');
pluralize.addSingularRule(/^(m|l)ice$/, '$1ouse');
pluralize.addSingularRule(/(bus|alias|[mpst]us|atlas|gas)(es)?$/, '$1');
pluralize.addSingularRule(/(e[mn]u)s?$/, '$1');
pluralize.addSingularRule(/(o)es$/, '$1');
pluralize.addSingularRule(/^(canoe)s$/, '$1');
pluralize.addSingularRule(/(shoe|movie|move)s$/, '$1');
pluralize.addSingularRule(/(cris|test|diagnos)(is|es)$/, '$1is');
pluralize.addSingularRule(/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc)(us|i)$/, '$1us');
pluralize.addSingularRule(/^(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi)a$/, '$1um');
pluralize.addSingularRule(/^(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|\w+hedr)a$/, '$1on');
pluralize.addSingularRule(/^(alumn|alg|vertebr)ae$/, '$1a');
pluralize.addSingularRule(/(cod|mur|sil|vert|ind)ices$/, '$1ex');
pluralize.addSingularRule(/(matr)ices$/, '$1ix');
pluralize.addSingularRule(/(pe)(rson|ople)$/, '$1rson');
pluralize.addSingularRule(/(child)ren$/, '$1');
pluralize.addSingularRule(/(eau)x$/, '$1');
pluralize.addSingularRule(/men$/, 'man');

// http://en.wikipedia.org/wiki/English_plural#Singulars_without_plurals
[
'advice', 'agenda', 'bison', 'bream', 'buffalo', 'carp', 'chassis',
'cod', 'cooperation', 'corps', 'digestion', 'debris', 'diabetes',
'energy', 'equipment', 'elk', 'excretion', 'expertise', 'flounder',
'gallows', 'graffiti', 'headquarters', 'health', 'herpes', 'highjinks',
'homework', 'information', 'jeans', 'justice', 'labour', 'machinery',
'mackerel', 'media', 'mews', 'money', 'moose', 'news', 'pike', 'plankton',
'pliers', 'pollution', 'rain', 'rice', 'salmon', 'scissors', 'series',
'sewage', 'shrimp', 'species', 'staff', 'swine', 'trout', 'tuna',
'whiting', 'wildebeest'
].forEach(pluralize.addUncountableRule);

// Uncountable regexes
pluralize.addUncountableRule(/pox$/);
pluralize.addUncountableRule(/ois$/);
pluralize.addUncountableRule(/deer$/);
pluralize.addUncountableRule(/fish$/);
pluralize.addUncountableRule(/sheep$/);
pluralize.addUncountableRule(/measles$/);
pluralize.addUncountableRule(/[nrlm]ese$/);
<|endoftext|>


<commit_before>'use strict';

var util = require('./lib/util');

exports = module.exports = Manifold;

// # Manifold constructor
//
function Manifold(){
  if(!(this instanceof Manifold)){
    return new Manifold();
  }

  this.parses = {};
  this.parse(util.defaultParsers);
  util.Parth.call(this);
}
util.inherits(Manifold, util.Parth);

// ## manifold.parse(prop[, parser])
// > parse properties before they are set
//
// arguments
//  - prop, type `string` or `object` with all parsers
//  - parser, optional, type `function`
//
// returns
//  - parser for less than two arguments
//  - this for two arguments
//
Manifold.prototype.parse = function(prop, parser){
  var propis = util.type(prop);
  if(propis.plainObject){
    return Object.keys(prop).forEach(function(key){
      return this.parse(key, prop[key]);
    }, this);
  }

  if(!parser && this.parses){
    return prop ? this.parses[prop] : util.parse;
  } else if(!propis.string){
    throw new TypeError('parse(prop[, parser])\n'+
      ' `prop` should be a string');
  } else if(typeof parser !== 'function'){
    throw new TypeError('parse(prop, parser):\n'+
      ' `parser`, if given, should be a function');
  }

  var self = this;
  this.parses[prop] = function(/* arguments */){
    return parser.apply(self, arguments);
  };

  return this;
};

// ## manifold.set(path[, options])
// setup path hierachy via regexes
//
// arguments
//  - `path` type string, function or plainObject
//  - `options` type function or plainObject
//
// returns this
//
Manifold.prototype.set = function(path, o){
  var pis = util.type(path), ois = util.type(o);
  if(!pis.match(/string|function|plainObject/)){
    throw new TypeError('set(path/options [, options]) '+
      '`path/options`, should be:' +
      ' - string (path)  ' +
      ' - function or plainObject (options)'
    );
  }

  o = ois.plainObject || pis.plainObject || '';
  var handle = pis.function || ois.function;
  if(handle){ o = o || {}; o.handle = handle; }

  var node = this.store;
  var stem = util.boil(path || o.path);
  if(stem && !node.children[stem.path]){
    this.add(stem.path);
    node = node.children[stem.path];
    util.defineProperty(node, 'regex', 'w');
    util.defineProperty(node, 'parent', 'w');
    util.defineProperty(node, 'children', 'w');
    // so properties are not copied by accident
  } else if(stem){
    node = node.children[stem.path];
  }

  if(!o){ return this; }
  Object.keys(o).forEach(function(key){
    var value = o[key];
    if(value === null){ delete node[key]; }
    else if(this.parses[key]){
      return this.parses[key](node, value, key, o);
    } else if(util.type(value).plainObject){
      if(!node[key]){ node[key] = {}; }
      util.merge(node[key], util.clone(value, true));
    } else { node[key] = util.clone(value, true); }
  }, this);

  return this;
};

// ## manifold.get([path, options, mod])
// > get object maching the given path
//
// arguments
//  - `path`, optional, type string
//  - `options`, optional, type object with all extra information
//  - `mod`, optional, modifiar depending the type
//    - boolean true, do not clone, return the node found by reference
//    - regular expresion, properties to skip on node found
//
// returns the object `node` found
//
var skipRE = /children|parent|regex/;

Manifold.prototype.get = function(path, opt, mod){
  var o = util.type(opt || path).object || {};
  var stem = this.match(path, o);
  var node = this.store;

  if(stem){ node = node.children[stem.path]; }
  if((mod || o.ref) === true){ return node; }

  var skip = util.type(mod || o).regexp || skipRE;

  while(node){
    for(var key in node){
      if(skip.test(key)){ continue; }
      if(util.has(o, key)){ continue; }
      o[key] = util.clone(node[key], true);
    }

    if(node.parent && node.path !== node.parent.path){
      node = node.parent;
    } else if(node){ node = null; }
  }

  return o;
};
<commit_msg>improvements: - better error message for manifold.set - make mod a ref to options if is not given - more performant manifold.get<commit_after>'use strict';

var util = require('./lib/util');

exports = module.exports = Manifold;

// # Manifold constructor
//
function Manifold(){
  if(!(this instanceof Manifold)){
    return new Manifold();
  }

  this.parses = {};
  this.parse(util.defaultParsers);
  util.Parth.call(this);
}
util.inherits(Manifold, util.Parth);

// ## manifold.parse(prop[, parser])
// > parse properties before they are set
//
// arguments
//  - prop, type `string` or `object` with all parsers
//  - parser, optional, type `function`
//
// returns
//  - parser for less than two arguments
//  - this for two arguments
//
Manifold.prototype.parse = function(prop, parser){
  var propis = util.type(prop);
  if(propis.plainObject){
    return Object.keys(prop).forEach(function(key){
      return this.parse(key, prop[key]);
    }, this);
  }

  if(!parser && this.parses){
    return prop ? this.parses[prop] : util.parse;
  } else if(!propis.string){
    throw new TypeError('parse(prop[, parser])\n'+
      ' `prop` should be a string');
  } else if(typeof parser !== 'function'){
    throw new TypeError('parse(prop, parser):\n'+
      ' `parser`, if given, should be a function');
  }

  var self = this;
  this.parses[prop] = function(/* arguments */){
    return parser.apply(self, arguments);
  };

  return this;
};

// ## manifold.set(path[, options])
// setup path hierachy via regexes
//
// arguments
//  - `path` type string, function or plainObject
//  - `options` type function or plainObject
//
// returns this
//
Manifold.prototype.set = function(path, o){
  var pis = util.type(path), ois = util.type(o);
  if(!pis.match(/string|function|plainObject/)){
    throw new TypeError('set(path/options [, options]). '+
      'Unsupported type for path/options.\n\n'+
      'Supported types are:\n'+
      ' - string (path)\n' +
      ' - plainObject (options)\n'
    );
  }

  o = ois.plainObject || pis.plainObject || '';
  var handle = pis.function || ois.function;
  if(handle){ o = o || {}; o.handle = handle; }

  var node = this.store;
  var stem = util.boil(path || o.path);
  if(stem && !node.children[stem.path]){
    this.add(stem.path);
    node = node.children[stem.path];
    util.defineProperty(node, 'regex', 'w');
    util.defineProperty(node, 'parent', 'w');
    util.defineProperty(node, 'children', 'w');
    // so properties are not copied by accident
  } else if(stem){
    node = node.children[stem.path];
  }

  if(!o){ return this; }
  Object.keys(o).forEach(function(key){
    var value = o[key];
    if(value === null){ delete node[key]; }
    else if(this.parses[key]){
      return this.parses[key](node, value, key, o);
    } else if(util.type(value).plainObject){
      if(!node[key]){ node[key] = {}; }
      util.merge(node[key], util.clone(value, true));
    } else { node[key] = util.clone(value, true); }
  }, this);

  return this;
};

// ## manifold.get([path, options, mod])
// > get object maching the given path, clone it if necessary
//
// arguments
//  - `path`, optional, type string
//  - `options`, optional, type object with all extra information
//  - `mod`, type object if is a
//    - regular expresion, props to skip while cloning found node
//    - plainObject with property ref, the node found will not be cloned
//
// returns the object `node` found
//
var skipRE = /children|parent|regex/;

Manifold.prototype.get = function(path, opt, mod){
  var o = util.type(opt || path).object || {};
  mod = mod || o;

  var stem = this.match(path, o);
  var node = this.store;

  if(stem){ node = node.children[stem.path]; }
  if(mod && mod.ref){ return node; }

  var skip = util.type(mod).regexp || skipRE;

  while(node){
    for(var key in node){
      if(skip.test(key)){ continue; }
      if(util.has(o, key)){ continue; }
      o[key] = util.clone(node[key], true);
    }

    if(node !== node.parent){
      node = node.parent;
    }
  }

  return o;
};
<|endoftext|>


<commit_before>var postcss = require('postcss');

module.exports = postcss.plugin('postcss-messages', function (opts) {
    if ( opts && opts.disabled === true ) {
        return function () { };
    };

    var styleKeys = ['display', 'padding', 'background', 'font-size', 'color', 'white-space'];

    var defaultStyles = {
      'display': 'block',
      'padding': '20px 30px',
      'background': 'red',
      'font-size': '16px',
      'color': 'white',
      'white-space': 'pre'
    };
    if ( opts && opts.styles ) {
      for ( var attrname in opts.styles ) {
        if ( opts.styles.hasOwnProperty(attrname) ) {
          defaultStyles[attrname] = opts.styles[attrname];
        };
      };
    };

    return function (css, result) {
        css.append({ selector: (opts && opts.selector) ? opts.selector : 'html:before' });
        for ( var style in defaultStyles ) {
          if ( defaultStyles.hasOwnProperty(style) ) {
            css.last.append({ prop: style, value: defaultStyles[style] });
          }
        };

        var content = result.warnings().map(function (message) {
            return message.toString().replace(/"/g, '\\"');
        }).join('\\00000a');

        css.last.append({ prop: 'content', value: '"' + content + '"' });
    };
});
<commit_msg>Remove unnecessary semicolons<commit_after>var postcss = require('postcss');

module.exports = postcss.plugin('postcss-messages', function (opts) {
    if ( opts && opts.disabled === true ) {
        return function () { };
    }

    var styleKeys = ['display', 'padding', 'background', 'font-size', 'color', 'white-space'];

    var defaultStyles = {
      'display': 'block',
      'padding': '20px 30px',
      'background': 'red',
      'font-size': '16px',
      'color': 'white',
      'white-space': 'pre'
    };
    if ( opts && opts.styles ) {
      for ( var attrname in opts.styles ) {
        if ( opts.styles.hasOwnProperty(attrname) ) {
          defaultStyles[attrname] = opts.styles[attrname];
        }
      }
    }

    return function (css, result) {
        css.append({ selector: (opts && opts.selector) ? opts.selector : 'html:before' });
        for ( var style in defaultStyles ) {
          if ( defaultStyles.hasOwnProperty(style) ) {
            css.last.append({ prop: style, value: defaultStyles[style] });
          }
        }

        var content = result.warnings().map(function (message) {
            return message.toString().replace(/"/g, '\\"');
        }).join('\\00000a');

        css.last.append({ prop: 'content', value: '"' + content + '"' });
    };
});
<|endoftext|>