'use strict';

class Keyv {
	constructor(opts) {
		this.opts = opts || {};
		this.opts.store = this.opts.store || new Map();
	}

	get(key) {
		const store = this.opts.store;
		return Promise.resolve(store.get(key)).then(data => {
			if (data === undefined) {
				return undefined;
			}
			if (!store.ttlSupport && Date.now() > data.expires) {
				this.delete(key);
				return undefined;
			}
			return store.ttlSupport ? data : data.value;
		});
	}

	set(key, value, ttl) {
		ttl = ttl || this.opts.ttl;
		const store = this.opts.store;
		let set;
		if (store.ttlSupport) {
			set = store.set(key, value, ttl);
		} else {
			const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : undefined;
			const data = { value, expires };
			set = store.set(key, data);
		}
		return Promise.resolve(set).then(() => value);
	}

	delete(key) {
		const store = this.opts.store;
		return Promise.resolve(store.delete(key));
	}
}

module.exports = Keyv;

'use strict';

class Keyv {
	constructor(opts) {
		this.opts = opts || {};
		this.opts.store = this.opts.store || new Map();
	}

	get(key) {
		const store = this.opts.store;
		return Promise.resolve(store.get(key)).then(data => {
			if (data === undefined) {
				return undefined;
			}
			if (!store.ttlSupport && Date.now() > data.expires) {
				this.delete(key);
				return undefined;
			}
			return store.ttlSupport ? data : data.value;
		});
	}

	set(key, value, ttl) {
		ttl = ttl || this.opts.ttl;
		const store = this.opts.store;
		let set;
		if (store.ttlSupport) {
			set = store.set(key, value, ttl);
		} else {
			const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : undefined;
			const data = { value, expires };
			set = store.set(key, data);
		}
		return Promise.resolve(set).then(() => value);
	}

	delete(key) {
		const store = this.opts.store;
		return Promise.resolve(store.delete(key));
	}

	clear() {
		const store = this.opts.store;
		return Promise.resolve(store.clear());
	}
}

module.exports = Keyv;

Add .clear() method to Keyv


import isPromise from './isPromise';

const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED']

export default function promiseMiddleware(config={}) {
  const promiseTypes = config.promiseTypes || defaultTypes;
  return () => {
    return next => action => {
      if (!isPromise(action.payload)) {
        return next(action);
      }

      const { type, payload, meta={} } = action;
      const { promise, data } = payload;
      const [ PENDING, FULFILLED, REJECTED ] = meta.promiseTypes || promiseTypes;

     /**
      * Dispatch the first async handler. This tells the
      * reducer that an async action has been dispatched.
      */
      next({
        type: `${type}_${PENDING}`,
        payload: data,
        meta
      });

      /**
       * Return either the fulfilled action object or the rejected
       * action object.
       */
      return promise.then(
        payload => next({
          type: `${type}_${FULFILLED}`,
          payload,
          meta,
        }),
        error => next({
          type: `${type}_${REJECTED}`,
          payload: error,
          error: true,
	  meta
        })
      );
    };
  }
}

import isPromise from './isPromise';

const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED']

export default function promiseMiddleware(config={}) {
  const promiseTypes = config.promiseTypes || defaultTypes;
  return () => {
    return next => action => {
      if (!isPromise(action.payload)) {
        return next(action);
      }

      const { type, payload, meta={} } = action;
      const { promise, data } = payload;
      const [ PENDING, FULFILLED, REJECTED ] = meta.promiseTypes || promiseTypes;

     /**
      * Dispatch the first async handler. This tells the
      * reducer that an async action has been dispatched.
      */
      next({
        type: `${type}_${PENDING}`,
        payload: data,
        ...meta || {}
      });

      /**
       * Return either the fulfilled action object or the rejected
       * action object.
       */
      return promise.then(
        payload => next({
          type: `${type}_${FULFILLED}`,
          payload,
          ...meta || {},
        }),
        error => next({
          type: `${type}_${REJECTED}`,
          payload: error,
          error: true,
          ...meta || {}
        })
      );
    };
  }
}

Remove empty meta objects from action


var inspect = require('eyes').inspector();
var awssum = require('awssum');
var oauth = awssum.load('oauth');
var tumblrService = awssum.load('tumblr/tumblr');

var env = process.env;
var consumerKey = process.env.TUMBLR_CONSUMER_KEY;
var consumerSecret = process.env.TUMBLR_CONSUMER_SECRET;

var tumblr = new tumblrService.Tumblr(consumerKey, consumerSecret);

console.log( 'OAuthConsumerKey :', tumblr.oauthConsumerKey() );
console.log( 'OAuthConsumerSecret :',  tumblr.oauthConsumerSecret() );

tumblr.RequestToken({ 'oauth_callback' : 'oob' }, function(err, data) {
    console.log("\nrequesting token - expecting success");
    inspect(err, 'Error');
    inspect(data, 'Data');
});

var inspect = require('eyes').inspector();
var awssum = require('awssum');
var oauth = awssum.load('oauth');
var tumblrService = awssum.load('tumblr/tumblr');

var env = process.env;
var consumerKey = process.env.TUMBLR_CONSUMER_KEY;
var consumerSecret = process.env.TUMBLR_CONSUMER_SECRET;
// don't need the token, tokenSecret or verifier

var tumblr = new tumblrService.Tumblr(consumerKey, consumerSecret);

console.log( 'ConsumerKey :', tumblr.consumerKey() );
console.log( 'ConsumerSecret :',  tumblr.consumerSecret() );

tumblr.RequestToken({ 'OAuthCallback' : 'oob' }, function(err, data) {
    console.log("\nrequesting token - expecting success");
    inspect(err, 'Error');
    if ( err ) {
        process.exit();
    }

    inspect(data, 'Data');
    console.log( 'If you want to verify this token, visit: '
                 + tumblr.protocol() + '://' + tumblr.authorizeHost()
                 + tumblr.authorizePath()
                 + '?oauth_token=' + data.Body.oauth_token
               );
});

Fix Tumblr a bit (though not complete)


module.exports = function removeSharedLibraries(project, libraries) {
  if (!libraries.length) {
    return;
  }

  const target = project.getFirstTarget().uuid;

  for (var name of libraries) {
    project.removeFramework(name, { target });
  }
};

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

module.exports = function removeSharedLibraries(project, libraries) {
  const group = getGroup(project, 'Frameworks');

  if (!libraries.length || !group) {
    return;
  }

  const target = project.getFirstTarget().uuid;

  for (var name of libraries) {
    project.removeFramework(name, { target });
  }
};

Make sure it works when unlinking


var i$getLine = function() {
    return prompt("Prelude.getLine");
}

var i$putStr = function(s) {
  console.log(s);
};

var i$systemInfo = function(index) {
  switch(index) {
    case 0:
      return "javascript";
    case 1:
      return navigator.platform;
  }
  return "";
}

Add a getLine primitive to browser js


function openerp_pos_ncf_widgets(instance, module) { //module is instance.point_of_sale
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    module.PosWidget = module.PosWidget.extend({

        start: function() {
            var self = this;
            this._super();

        },

        // This method instantiates all the screens, widgets, etc. If you want to add new screens change the
        // startup screen, etc, override this method.
        build_widgets: function () {
            var self = this;
            this._super();

            // --------  New Screens definitions.

            this.orderlist_screen = new module.PendingOrderListScreenWidget(this, {});
            this.orderlist_screen.appendTo(this.$('.screens'));

            // -------- Misc.

            if (false) {// TODO: implement configurable parameter for the POS to allow unpaid orders.
                this.pendingorders_button = new module.HeaderButtonWidget(this, {
                    label: _t('Ordenes Pendientes'),
                    action: function () {
                        self.screen_selector.set_current_screen('orderlist', {}, true);
                    }
                });
                this.pendingorders_button.appendTo(this.$('.pos-rightheader'));
            }

            // --------  Adding Pending Order Screen to screen_selector.

            this.screen_selector.add_screen('orderlist', this.orderlist_screen);

        }
    });
}

function openerp_pos_ncf_widgets(instance, module) { //module is instance.point_of_sale
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    module.PosWidget = module.PosWidget.extend({
        // This method instantiates all the screens, widgets, etc. If you want to add new screens change the
        // startup screen, etc, override this method.
        build_widgets: function () {
            var self = this;
            this._super();

            if (false) {// TODO: implement configurable parameter for the POS to allow unpaid orders.
                // --------  New Screens definitions.
                this.orderlist_screen = new module.PendingOrderListScreenWidget(this, {});
                this.orderlist_screen.appendTo(this.$('.screens'));

                // -------- Misc.
                this.pendingorders_button = new module.HeaderButtonWidget(this, {
                    label: _t('Ordenes Pendientes'),
                    action: function () {
                        self.screen_selector.set_current_screen('orderlist', {}, true);
                    }
                });
                this.pendingorders_button.appendTo(this.$('.pos-rightheader'));

                // --------  Adding Pending Order Screen to screen_selector.
                this.screen_selector.add_screen('orderlist', this.orderlist_screen);
            }
        }
    });
}

Optimize pending order screen load


angular.module('caco.feed.crtl')
    .controller('FeedManageCrtl', function ($rootScope, $scope, $stateParams, $location, Feeds, FeedREST, FeedUrlLookupREST) {
        $rootScope.module = 'feed';
        $rootScope.modulePath = $location.path();

        Feeds.get(function (feeds) {
            $scope.feeds = feeds;
        });

        if ($stateParams.id) {
            Feeds.getOne($stateParams.id, function (feed) {
                $scope.feed = feed;
            })
        }

        $scope.lookup = function () {
            FeedUrlLookupREST.lookup({q: $scope.lookupUrl}, {}, function (data) {
                if (data && data.responseStatus == 200) {
                    $scope.feed = data.responseData;
                }
            });
        };

        $scope.add = function () {
            Feeds.add($scope.feed, function (feeds) {
                $scope.feeds = feeds;
                $location.path('/feed/manage');
            });
        };

        $scope.edit = function () {
            Feeds.edit($scope.feed, function (feeds) {
                $scope.feeds = feeds;
                $location.path('/feed/manage');
            });
        };

        $scope.delete = function (id) {
            if (!confirm('Confirm delete')) {
                return;
            }

            Feeds.remove({id: id}, function (feeds) {
                $scope.feeds = feeds;
                $location.path('/feed/manage');
            });
        };
    });

angular.module('caco.feed.crtl')
    .controller('FeedManageCrtl', function ($rootScope, $scope, $stateParams, $location, Feeds, FeedREST, FeedUrlLookupREST) {
        $rootScope.module = 'feed';
        $rootScope.modulePath = $location.path();

        if ($stateParams.id) {
            Feeds.getOne($stateParams.id, function (feed) {
                $scope.feed = feed;
            })
        } else {
            Feeds.get(function (feeds) {
                $scope.feeds = feeds;
            });
        }

        $scope.lookup = function () {
            FeedUrlLookupREST.lookup({q: $scope.lookupUrl}, {}, function (data) {
                if (data && data.responseStatus == 200) {
                    $scope.feed = data.responseData;
                }
            });
        };

        $scope.add = function () {
            Feeds.add($scope.feed, function (feeds) {
                $scope.feeds = feeds;
                $location.path('/feed/manage');
            });
        };

        $scope.edit = function () {
            Feeds.edit($scope.feed, function (feeds) {
                $scope.feeds = feeds;
                $location.path('/feed/manage');
            });
        };

        $scope.delete = function (id) {
            if (!confirm('Confirm delete')) {
                return;
            }

            Feeds.remove({id: id}, function (feeds) {
                $scope.feeds = feeds;
                $location.path('/feed/manage');
            });
        };
    });

Save one request at feed managing.


import chalk from 'chalk'
import getUserConfig from '../../util/getUserConfig'

export default {
  name: 'logout',
  signature: 'logout',
  description: 'Logs out of the Sanity.io session',
  async action(args, {output, prompt, apiClient}) {
    const cfg = getUserConfig()

    const token = cfg.get('authToken')
    const type = cfg.get('authType')
    if (!token) {
      output.print(chalk.red('No login credentials found'))
      return
    }

    if (token && type !== 'provisional') {
      logout(cfg)
      return
    }

    if (type === 'provisional') {
      output.print(chalk.yellow.inverse('[WARN]') + chalk.yellow(' You are currently logged in as a temporary user!'))
      output.print(chalk.yellow('Logging out will make it super hard to claim your beautiful project :\'('))
    }

    const confirm = await prompt.single({
      type: 'confirm',
      message: 'Are you sure you want to log out?',
      default: false
    })

    if (!confirm) {
      output.print(chalk.red('Aborted'))
      return
    }

    logout(cfg)

    async function logout() {
      const client = apiClient({requireUser: false, requireProject: false})
      if (token) {
        await client.request({url: '/auth/logout'})
      }

      cfg.del('authType')
      cfg.del('authToken')

      output.print(chalk.green('Logged out'))
    }
  }
}

import chalk from 'chalk'
import getUserConfig from '../../util/getUserConfig'

export default {
  name: 'logout',
  signature: 'logout',
  description: 'Logs out of the Sanity.io session',
  async action(args, {output, prompt, apiClient}) {
    const cfg = getUserConfig()

    const token = cfg.get('authToken')
    const type = cfg.get('authType')
    if (!token) {
      output.print(chalk.red('No login credentials found'))
      return
    }

    if (token && type !== 'provisional') {
      logout(cfg)
      return
    }

    if (type === 'provisional') {
      output.print(chalk.yellow.inverse('[WARN]') + chalk.yellow(' You are currently logged in as a temporary user!'))
      output.print(chalk.yellow('Logging out will make it super hard to claim your beautiful project :\'('))
    }

    const confirm = await prompt.single({
      type: 'confirm',
      message: 'Are you sure you want to log out?',
      default: false
    })

    if (!confirm) {
      output.print(chalk.red('Aborted'))
      return
    }

    logout(cfg)

    async function logout() {
      const client = apiClient({requireUser: false, requireProject: false})
      if (token) {
        await client.request({uri: '/auth/logout'})
      }

      cfg.del('authType')
      cfg.del('authToken')

      output.print(chalk.green('Logged out'))
    }
  }
}

Fix incorrect option causing crash on logout


/*
 * Author: CM
 * Dependencies: jquery.transit.js
 */
(function($) {

  $.clickDecorators.feedback = {
    isApplicable: function($element) {
      return $element.is('.button');
    },

    before: function(event) {
      var $this = $(this);
      var buttonOffset = $this.offset();
      var feedbackSize = 2 * Math.sqrt(Math.pow($this.outerWidth(), 2) + Math.pow($this.outerHeight(), 2));

      var posX = event.pageX;
      var posY = event.pageY;

      var $feedback = $('<div class="click-feedback" />');
      $feedback.css({
        width: feedbackSize,
        height: feedbackSize,
        left: posX - buttonOffset.left - (feedbackSize / 2),
        top: posY - buttonOffset.top - (feedbackSize / 2)
      });
      $this.append($feedback);
      $feedback.transition({
        scale: 1
      }, '300ms', 'in', function() {
        $feedback.remove();
      });
    }
  };

})(jQuery);

/*
 * Author: CM
 * Dependencies: jquery.transit.js
 */
(function($) {

  $.clickDecorators.feedback = {
    isApplicable: function($element) {
      return $element.is('.button, .menu a');
    },

    before: function(event) {
      var $this = $(this);
      var buttonOffset = $this.offset();
      var feedbackSize = 2 * Math.sqrt(Math.pow($this.outerWidth(), 2) + Math.pow($this.outerHeight(), 2));

      var posX = event.pageX;
      var posY = event.pageY;

      var $feedback = $('<div class="click-feedback" />');
      $feedback.css({
        width: feedbackSize,
        height: feedbackSize,
        left: posX - buttonOffset.left - (feedbackSize / 2),
        top: posY - buttonOffset.top - (feedbackSize / 2)
      });
      $this.append($feedback);
      $feedback.transition({
        scale: 1
      }, '300ms', 'in').transition({
        opacity: 0
      }, '200ms', 'out', function() {
        $feedback.remove();
      });
    }
  };

})(jQuery);

Improve click feedback transition, extend to menus


/*globals $, GOVUK, suchi */
/*jslint
 white: true,
 browser: true */

$(function() {
  "use strict";
  function browserWarning() {
    var container = $('

'),
        text = $('
For a safer, faster, better experience online you should upgrade your browser.
'),
        findMoreLink = $('Find out more about browsers'),
        closeLink = $('Close');

    return container.append(text.append(findMoreLink, closeLink));
  }

  // we don't show the message when the cookie warning is also there
  if (GOVUK.cookie('seen_cookie_message')) {
    if (suchi.isOld(navigator.userAgent)) {
      if(GOVUK.cookie('govuk_not_first_visit') !== null && GOVUK.cookie('govuk_browser_upgrade_dismissed') === null){
        var $prompt = browserWarning();
        $('#global-cookie-message').after($prompt);
        $prompt.show();
        $prompt.on("click", ".dismiss", function(e) {
          $prompt.hide();
          // the warning is dismissable for 2 weeks
          GOVUK.cookie('govuk_browser_upgrade_dismissed', 'yes', { days: 14 });
        });
      }
    }

    // We're not showing the message on first visit
    GOVUK.cookie('govuk_not_first_visit', 'yes', { days: 28 });
  }
});

Add missing space before link


// var txtTarget = $('.main_cover');
// var txt = txtTarget.html() || '';
// var leng = txt.length || 0;
// var timer = '';
// var cnt = 0;

// $(window).load(function () {
//     if (txtTarget) {
//         txtTarget.css('opacity', 1);
//         typing();
//     }
// });

// function typing() {
//     txtTarget.html(txt.substring(0, cnt) + '_');
//     cnt++;
//     timer = setTimeout('typing()', 100);
//     if (leng < cnt) {
//         clearTimeout(timer);
//         cnt = 0;
//     }
// }

// TYPED.JS
$(document).ready(function(){
    $("#typed").typed({
        strings: [
            "HTML5.", "CSS3.", "Sass.", "Bootstrap.", "JavaScript.", "jQuery.",
            "Node.js.", "Express.", "Socket.io.", "MongoDB."
        ],
        typeSpeed: 120,
        startDelay: 0,
        backSpeed: 80,
        backDelay: 800,
        loop: true
    });
});

// var txtTarget = $('.main_cover');
// var txt = txtTarget.html() || '';
// var leng = txt.length || 0;
// var timer = '';
// var cnt = 0;

// $(window).load(function () {
//     if (txtTarget) {
//         txtTarget.css('opacity', 1);
//         typing();
//     }
// });

// function typing() {
//     txtTarget.html(txt.substring(0, cnt) + '_');
//     cnt++;
//     timer = setTimeout('typing()', 100);
//     if (leng < cnt) {
//         clearTimeout(timer);
//         cnt = 0;
//     }
// }

// TYPED.JS
$(document).ready(function () {
    $("#typed").typed({
        // strings: [
        //     "HTML5.", "CSS3.", "Sass.", "Bootstrap.", "JavaScript.", "jQuery.",
        //     "Node.js.", "Express.", "Socket.io.", "MongoDB."
        // ],
        strings: [
            "HTML5.", "CSS3.", "Sass.", "JavaScript.", "jQuery.", "Node.js.", "Git"
        ],
        typeSpeed: 120,
        startDelay: 0,
        backSpeed: 80,
        backDelay: 800,
        loop: true
    });
});

Modify text about Typed js


// Wraps any value with promise. Not very useful on its own, used internally
// by deferred.js

'use strict';

var curry       = require('es5-ext/lib/Function/curry').call
  , isFunction  = require('es5-ext/lib/Function/is-function')
  , noop        = require('es5-ext/lib/Function/noop')
  , sequence    = require('es5-ext/lib/Function/sequence').call

  , isPromise   = require('./is-promise')

  , deferred, then, throwError, end;

then = function (value, ignore, callback) {
	var d = deferred();
	setTimeout(callback ?
		sequence(curry(callback, value), d.resolve) :
		d.resolve.bind(d, value), 0);
	return d.promise;
};

throwError = function () {
	throw this;
};

end = function (handler) {
	setTimeout(
		isFunction(handler) ? curry(handler, this) : throwError.bind(this), 0);
};

module.exports = function (value) {
	var r;
	if (isPromise(value)) {
		return value;
	} else if (value instanceof Error) {
		r = curry(then, value);
		r.end = end.bind(value);
	} else {
		r = curry(then, value, null);
		r.end = noop;
	}
	return r.then = r;
};

deferred = require('./deferred');

// Wraps any value with promise. Not very useful on its own, used internally
// by deferred.js

'use strict';

var curry       = require('es5-ext/lib/Function/curry').call
  , isFunction  = require('es5-ext/lib/Function/is-function')
  , noop        = require('es5-ext/lib/Function/noop')
  , sequence    = require('es5-ext/lib/Function/sequence').call
  , nextTick    = require('clock/lib/next-tick')

  , isPromise   = require('./is-promise')

  , deferred, then, throwError, end;

then = function (value, ignore, callback) {
	var d = deferred();
	nextTick(callback ?
		sequence(curry(callback, value), d.resolve) :
		d.resolve.bind(d, value));
	return d.promise;
};

throwError = function () {
	throw this;
};

end = function (handler) {
	nextTick(
		isFunction(handler) ? curry(handler, this) : throwError.bind(this));
};

module.exports = function (value) {
	var r;
	if (isPromise(value)) {
		return value;
	} else if (value instanceof Error) {
		r = curry(then, value);
		r.end = end.bind(value);
	} else {
		r = curry(then, value, null);
		r.end = noop;
	}
	return r.then = r;
};

deferred = require('./deferred');

Use process.nextTick instead of setTimeout if available


var path = require('path');

var loadHelpers = require('./load-helpers');

module.exports = function(sails) {

  return {

    /**
     * Before any hooks have begun loading...
     * (called automatically by Sails core)
     */
    configure: function() {
      sails.helpers = {};
    },

    initialize: function(cb) {

      var self = this;

      // Load helpers from the specified folder
      loadHelpers.apply(this, [sails, cb]);

    },

    reload: function(helpers) {
      // If we received an explicit set of helpers to load, use them.
      if (helpers) {
        sails.helpers = helpers;
        return;
      }
      // Otherwise reload helpers from disk.
      loadHelpers.apply(this, [sails, function(err) {
        if (err) {throw err;}
      }]);
    }

  };

};

var path = require('path');

var loadHelpers = require('./load-helpers');

module.exports = function(sails) {

  return {

    /**
     * Before any hooks have begun loading...
     * (called automatically by Sails core)
     */
    configure: function() {
      sails.helpers = {};
    },

    initialize: function(cb) {

      var self = this;

      // Load helpers from the specified folder
      loadHelpers.apply(this, [sails, cb]);

    },

    reload: function(helpers, cb) {

      if (typeof helpers === 'function') {
        cb = helpers;
        helpers = null;
      }

      // If we received an explicit set of helpers to load, use them.
      if (helpers) {
        sails.helpers = helpers;
        return;
      }
      // Otherwise reload helpers from disk.
      loadHelpers.apply(this, [sails, function(err) {
        if (cb) {
          return cb(err);
        }
        if (err) {
          throw err;
        }
      }]);
    }

  };

};

Add optional callback to `reload` method in helpers hook


'use strict';

var React = require('react-native');
var AddEntryPage = require('./app/components/addEntryPage/addEntryPage');

var {
    StyleSheet,
    Component,
    AppRegistry,
    NavigatorIOS
} = React;

var styles = StyleSheet.create({
    container: {
        flex: 1
    }
});

class MoveItIOS extends Component {
  render() {
    return (
        <NavigatorIOS
        barTintColor="#FDC300"
        style={styles.container}
        initialRoute={{
            title: 'Add Entry',
            component: AddEntryPage
        }}
        />
    );
  }
}

AppRegistry.registerComponent('MoveItIOS', () => MoveItIOS);

'use strict';

var React = require('react-native');
var AddEntryPage = require('./app/components/addEntryPage/addEntryPage');
var Leaderboard = require('./app/components/leaderboard/leaderboard');

var {
  StyleSheet,
  Component,
  AppRegistry,
  NavigatorIOS
} = React;

var styles = StyleSheet.create({
  container: {
    flex: 1
  }
});

class MoveItIOS extends Component {
  render() {
    return (
      <NavigatorIOS
        ref="nav"
        barTintColor="#FDC300"
        style={styles.container}
        initialRoute={{
          title: 'Add Entry',
          component: AddEntryPage,
          rightButtonTitle: 'Cancel',
          onRightButtonPress: () => {
            this.refs.nav.navigator.push({
              title: 'Leaderboard',
              component: Leaderboard
            })
          }
        }}
        />
    );
  }
}

AppRegistry.registerComponent('MoveItIOS', () => MoveItIOS);

Add navigation links in the navbar


'use strict';

const { autoUpdater } = require("electron-updater");
const log = require("electron-log");
const { dialog } = require('electron')

autoUpdater.logger = log;

function setUp() {
    autoUpdater.checkForUpdates();
}

autoUpdater.autoDownload = false;

autoUpdater.on('error', (error) => {
    dialog.showErrorBox(
        'Error: ',
        error == null ? "unknown" : (error.stack || error).toString()
    );
});

autoUpdater.on('update-available', () => {
    dialog.showMessageBox({
        type: 'info',
        title: 'Update verfügbar',
        message: 'Eine neue Version von iDAI.field ist verfügbar. Möchten Sie sie herunterladen?',
        buttons: ['Ja', 'Nein']
    }, (buttonIndex) => {
        if (buttonIndex === 0) {
            autoUpdater.downloadUpdate();
        }
    });
});

autoUpdater.on('update-downloaded', () => {
    dialog.showMessageBox({
        title: 'Update installieren',
        message: 'Die neue Version von iDAI.field wurde geladen. Möchten Sie die Anwendung jetzt neustarten um die neue Version zu installieren?',
        buttons: ['Ja', 'Nein']
    }, (buttonIndex) => {
        if (buttonIndex === 0) {
            autoUpdater.quitAndInstall();
        }
    });
});

module.exports = {
    setUp: setUp
};

'use strict';

const { autoUpdater } = require("electron-updater");
const log = require("electron-log");
const { dialog } = require('electron')

autoUpdater.logger = log;

function setUp() {
    autoUpdater.checkForUpdates();
}

autoUpdater.autoDownload = false;

autoUpdater.on('error', (error) => {
    dialog.showErrorBox(
        'Error: ',
        error == null ? "unknown" : (error.stack || error).toString()
    );
});

autoUpdater.on('update-available', () => {
    dialog.showMessageBox({
        type: 'info',
        title: 'Update verfügbar',
        message: 'Eine neue Version von iDAI.field ist verfügbar. Möchten Sie sie herunterladen?',
        buttons: ['Ja', 'Nein']
    }, (buttonIndex) => {
        if (buttonIndex === 0) {
            autoUpdater.downloadUpdate();
        }
    });
});

autoUpdater.on('update-downloaded', () => {
    dialog.showMessageBox({
        title: 'Update installieren',
        message: 'Die neue Version von iDAI.field wurde geladen. Starten Sie die Anwendung neu um sie zu installieren.',
    });
});

module.exports = {
    setUp: setUp
};

Remove options in update-downloaded dialog


/*
  Copyright 2018 Google LLC

  Use of this source code is governed by an MIT-style
  license that can be found in the LICENSE file or at
  https://opensource.org/licenses/MIT.
*/

module.exports = {
  clientsClaim: false,
  globFollow: true,
  globIgnores: ['**/node_modules/**/*'],
  globPatterns: ['**/*.{js,css,html}'],
  globStrict: true,
  importWorkboxFrom: 'cdn',
  injectionPointRegexp: /(\.precacheAndRoute\()\s*\[\s*\]\s*(\)|,)/,
  maximumFileSizeToCacheInBytes: 2 * 1024 * 1024,
  navigateFallback: undefined,
  offlineGoogleAnalytics: false,
  purgeOnQuotaError: false,
  skipWaiting: false,
};

/*
  Copyright 2018 Google LLC

  Use of this source code is governed by an MIT-style
  license that can be found in the LICENSE file or at
  https://opensource.org/licenses/MIT.
*/

module.exports = {
  clientsClaim: false,
  globFollow: true,
  globIgnores: ['**/node_modules/**/*'],
  globPatterns: ['**/*.{js,css,html}'],
  globStrict: true,
  importWorkboxFrom: 'cdn',
  injectionPointRegexp: /(precacheAndRoute\()\s*\[\s*\]\s*(\)|,)/,
  maximumFileSizeToCacheInBytes: 2 * 1024 * 1024,
  navigateFallback: undefined,
  offlineGoogleAnalytics: false,
  purgeOnQuotaError: false,
  skipWaiting: false,
};

Make injectionPointRegexp more bundler friendly


jest.dontMock('fs');
jest.dontMock('path');
jest.dontMock(SRC_DIRECTORY + '/cliopts');

describe('cliopts.getCLIOptions', () =>
{

  it('Should get the correct CLI options from the passed object', () =>
  {
    var cliopts = require(SRC_DIRECTORY + '/cliopts');

    var input = {
      package  : 'Cady',
      modules  : 'Regina',
      renderer : 'Gretchen',
      otherOpt : 'Janis'
    };

    var expected = {
      package  : 'Cady',
      modules  : 'Regina',
      renderer : 'Gretchen'
    };

    expect(cliopts.getCLIOptions(input)).toEqual(expected);
  });

});

jest.dontMock('fs');
jest.dontMock('path');
jest.dontMock(SRC_DIRECTORY + '/cliopts');

describe('cliopts.getCLIOptions', () =>
{

  it('Should get the correct CLI options from the passed object', () =>
  {
    var cliopts = require(SRC_DIRECTORY + '/cliopts');

    var input = {
      package  : 'Cady',
      modules  : 'Regina',
      renderer : 'Gretchen',
      otherOpt : 'Janis'
    };

    var expected = {
      package  : 'Cady',
      modules  : 'Regina',
      renderer : 'Gretchen',
      strict   : false
    };

    expect(cliopts.getCLIOptions(input)).toEqual(expected);
  });

});

Fix failing test following strict cli opt addition


import { Base } from 'yeoman-generator';
import generatorArguments from './arguments';
import generatorOptions from './options';
import generatorSteps from './steps';

export default class AdapterGenerator extends Base {
  constructor(...args) {
    super(...args);

    Object.keys(generatorArguments).forEach(key => this.argument(key, generatorArguments[key]));
    Object.keys(generatorOptions).forEach(key => this.option(key, generatorOptions[key]));
  }

  get configuring() {
    return generatorSteps.configuring;
  }

  get conflicts() {
    return generatorSteps.conflicts;
  }

  get default() {
    return generatorSteps.default;
  }

  get end() {
    return generatorSteps.end;
  }

  get initializing() {
    return generatorSteps.initializing
  }

  get install() {
    return generatorSteps.install;
  }

  get prompting() {
    return generatorSteps.prompting
  }

  get writing() {
    return generatorSteps.writing;
  }
}

import { Base } from 'yeoman-generator';
import generatorArguments from './arguments';
import generatorOptions from './options';
import generatorSteps from './steps';

export default class AdapterGenerator extends Base {
  constructor(...args) {
    super(...args);

    Object.keys(generatorArguments).forEach(key => this.argument(key, generatorArguments[key]));
    Object.keys(generatorOptions).forEach(key => this.option(key, generatorOptions[key]));

    this.description = 'Scaffolds a custom adapter for Sails in api/adapters folder';
  }

  get configuring() {
    return generatorSteps.configuring;
  }

  get conflicts() {
    return generatorSteps.conflicts;
  }

  get default() {
    return generatorSteps.default;
  }

  get end() {
    return generatorSteps.end;
  }

  get initializing() {
    return generatorSteps.initializing
  }

  get install() {
    return generatorSteps.install;
  }

  get prompting() {
    return generatorSteps.prompting
  }

  get writing() {
    return generatorSteps.writing;
  }
}

Add description to adapter generator


import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
import './Harta.css';

const Participant = ({ text, color }) => {
  return (
    <div
      style={color}
      className="avatar-participant">
      <span>{text}</span>
    </div>
  );
};

export default class Harta extends Component {
  constructor(props) {
    super(props);
    this.state = {
      culoriParticipanti: []
    };
  }

  static defaultProps = {
    center: {lat: 47.6401534, lng: 26.2572495},
    zoom: 17,
    participanti: {},
  };

  render() {
    const participant = this.props.participanti.map((p, index) => {
      return <Participant key={index}
        lat={p.lastLocation.latitude}
        lng={p.lastLocation.longitude}
        text={p.id}
      />;
    });

    return (
      <GoogleMapReact
        defaultCenter={this.props.center}
        defaultZoom={this.props.zoom}
      >{participant}</GoogleMapReact>
    );
  }
}

import React, { Component } from 'react';
import GoogleMapReact from 'google-map-react';
import './Harta.css';

const Participant = ({ text, color }) => {
  return (
    <div
      style={color}
      className="avatar-participant">
      <span>{text}</span>
    </div>
  );
};

const createMapOptions = (maps) => {
  return {
    mapTypeId: maps.MapTypeId.SATELLITE
  }
}

export default class Harta extends Component {
  constructor(props) {
    super(props);
    this.state = {
      culoriParticipanti: []
    };
  }

  static defaultProps = {
    center: {lat: 47.6401534, lng: 26.2572495},
    zoom: 17,
    participanti: {},
  };

  render() {
    const participant = this.props.participanti.map((p, index) => {
      return <Participant key={index}
        lat={p.lastLocation.latitude}
        lng={p.lastLocation.longitude}
        text={p.id}
      />;
    });

    return (
      <GoogleMapReact
        defaultCenter={this.props.center}
        defaultZoom={this.props.zoom}
        options={createMapOptions}
      >{participant}</GoogleMapReact>
    );
  }
}

Set map type to satellite


// npm dependencies
const mongoose = require('mongoose');

// Defines Destination model
let Destination = mongoose.model('Destination', {
	img: {
		type: String
	},
	title: {
		type: String,
		required: true,
		minlength: 5,
		trim: true
	},
	description: {
		type: String,
		minlength: 10,
		trim: true
	},
	rate: {
		type: Number,
		default: null
	}
});

module.exports = {
	Destination
};

// npm dependencies
const mongoose = require('mongoose');

// Defines Destination model
let Destination = mongoose.model('Destination', {
	img: {
		type: String
	},
	title: {
		type: String,
		required: true,
		minlength: 5
	},
	state: {
		type: String,
	}
	country: {
		type: String,
		required: true,
	},
	continent: {
		string: String,
		required: true
	}
	description: {
		type: String,
		minlength: 10
	},
	rate: {
		type: Number,
		default: null
	}
});

module.exports = {
	Destination
};

Add fields to Destination model


// Global registry for our Redis connection.
// Use this instead of passing around a single 'client' handle.
// Also allows us to select a database within Redis.
var redis = require("redis");
var _ = require("underscore");

var client;
var db = 0;

var sessionclient;
var session_db = 1;

exports.initClient = function(select_db) {
    client = redis.createClient();
    if (select_db) {db = select_db;}
    client.select(db,function(){});
    return client;
};

exports.getClient = function() {
    if (_.isUndefined(client)) {
        console.log("Error: client has not been initialized");
    }
    return client;
};

exports.initSessionClient = function(select_db) {
    sessionclient = redis.createClient();
    if (select_db) {session_db = select_db;}
    sessionclient.select(session_db,function(){});
    return sessionclient;
};

exports.getSessionClient = function() {
    if (_.isUndefined(client)) {
        console.log("Error: session client has not been initialized");
    }
    return sessionclient;
};

// Global registry for our Redis connection.
// Use this instead of passing around a single 'client' handle.
// Also allows us to select a database within Redis.
var redis = require("redis");
var _ = require("underscore");

var client;
var db = 0;

var sessionclient;
var session_db = 1;

exports.initClient = function(select_db) {
    client = redis.createClient();
    //redis.debug_mode = true;
    if (select_db) {db = select_db;}
    client.select(db,function(){});
    return client;
};

exports.getClient = function() {
    if (_.isUndefined(client)) {
        console.log("Error: client has not been initialized");
    }
    return client;
};

exports.initSessionClient = function(select_db) {
    sessionclient = redis.createClient();
    if (select_db) {session_db = select_db;}
    sessionclient.select(session_db,function(){});
    return sessionclient;
};

exports.getSessionClient = function() {
    if (_.isUndefined(client)) {
        console.log("Error: session client has not been initialized");
    }
    return sessionclient;
};

Debug mode for redis (commented out).


import { Map } from 'immutable';

export const lastStateInit = new Map();

export function stateIterator(state, callback) {
  return state.forEach(callback);
}

export function stateGetter(state, key) {
 return state.get(key)
};

export function stateSetter(state, key, value) {
 return state.set(key, value)
};

export function stateReconciler(state, inboundState, reducedState, logger) {
 let newState = new Map();

 Object.keys(inboundState).forEach((key) => {
   // if initialState does not have key, skip auto rehydration
   if (!state.has(key)) return

   // if reducer modifies substate, skip auto rehydration
   if (state.get('key') !== reducedState.get('key')) {
     if (logger) console.log('redux-persist/autoRehydrate: sub state for key `%s` modified, skipping autoRehydrate.', key)
     newState = newState.set(key, reducedState.get(key))
     return
   }

   // otherwise take the inboundState
   if (state.has(key)) {
     newState = state.merge(inboundState) // shallow merge
   } else {
     newState = state.set(key, inboundState[key]) // hard set
   }

   if (logger) console.log('redux-persist/autoRehydrate: key `%s`, rehydrated to ', key, newState[key])
 })

 return newState
};

import { Map } from 'immutable';

export const lastStateInit = new Map();

export function stateIterator(state, callback) {
  return state.forEach(callback);
}

export function stateGetter(state, key) {
 return state.get(key)
};

export function stateSetter(state, key, value) {
 return state.set(key, value)
};

export function stateReconciler(state, inboundState, reducedState, logger) {
 let newState = reducedState ? reducedState : new Map();

 Object.keys(inboundState).forEach((key) => {
   // if initialState does not have key, skip auto rehydration
   if (!state.has(key)) return

   // if reducer modifies substate, skip auto rehydration
   if (state.get('key') !== reducedState.get('key')) {
     if (logger) console.log('redux-persist/autoRehydrate: sub state for key `%s` modified, skipping autoRehydrate.', key)
     newState = newState.set(key, reducedState.get(key))
     return
   }

   // otherwise take the inboundState
   if (state.has(key)) {
     newState = state.merge(inboundState) // shallow merge
   } else {
     newState = state.set(key, inboundState[key]) // hard set
   }

   if (logger) console.log('redux-persist/autoRehydrate: key `%s`, rehydrated to ', key, newState[key])
 })

 return newState
};

Fix if inbound state in none


/* eslint-disable no-console */
console.log('hi');
// Old ES5 way of creating a Class Component
// var HelloWorld = React.createClass({
//   render: function() {
//     return (
//
Hello World!

//     );
//   };
// });

Add example of ES5 create class component


export default function (opts = {}) {
  const isJsonFile = opts.filter || /\.json$/;
  return (override, transform) => {
    transform("readSource", function (source, [module]) {
      if (isJsonFile.test(module.path)) {
        source = `module.exports = ${source};`;
      }
      return source;
    });
  };
}

export default function (opts = {}) {
  const isJsonFile = opts.filter || /\.json$/;
  return (override, transform) => {
    transform("readSource", function (module) {
      if (isJsonFile.test(module.path)) {
        module = Object.assign({}, module, {
          rawSource: `module.exports = ${module.rawSource};`
        });
      }
      return module;
    });
  };
}

Bring `readSource` transform up-to-date with Interlock API.


function isFunction (obj) {
  return !!(obj && obj.constructor && obj.call && obj.apply)
}

function createActionHandler (ignore) {
  // redux-ignore higher order reducer
  return function handleAction (reducer, actions = []) {
    const predicate = isFunction(actions)
        ? actions
        : (action) => actions.indexOf(action.type) >= 0

    return (state, action) => {
      if (predicate(action)) {
        return ignore ? state : reducer(state, action)
      }

      return ignore ? reducer(state, action) : state
    }
  }
}

export const ignoreActions = createActionHandler(true)
export const filterActions = createActionHandler(false)

export default ignoreActions
// /redux-ignore

function isFunction (obj) {
  return !!(obj && obj.constructor && obj.call && obj.apply)
}

function createActionHandler (ignore) {
  // redux-ignore higher order reducer
  return function handleAction (reducer, actions = []) {
    const predicate = isFunction(actions)
        ? actions
        : (action) => actions.indexOf(action.type) >= 0

    const initialState = reducer(undefined, {})

    return (state = initialState, action) => {
      if (predicate(action)) {
        return ignore ? state : reducer(state, action)
      }

      return ignore ? reducer(state, action) : state
    }
  }
}

export const ignoreActions = createActionHandler(true)
export const filterActions = createActionHandler(false)

export default ignoreActions
// /redux-ignore

Add default state to handleAction's return fn


"use strict";

var db     = require("./lib/firebase"),
    routes = require("./routes");

// Don't actually want the exports, just want it bundled
require("./global.css");

// IIFE so I can return w/o complaints from ESLint
(function() {
    if(!global.crucible) {
        return routes.setup();
    }

    if(!db.getAuth()) {
        return routes.unauth();
    }

    routes.default();
}());

"use strict";

var db     = require("./lib/firebase"),
    routes = require("./routes");

// Don't actually want the exports, just want it bundled
require("./global.css");

// IIFE so I can return w/o complaints from ESLint
(function() {
    if(!global.crucible) {
        return routes.setup();
    }

    if(global.crucsaible.auth && !db.getAuth()) {
        return routes.unauth();
    }

    routes.default();
}());

Check config for auth before asking user for auth


'use strict';

const childProcess = require('child-process-promise');
const express = require('express');
const path = require('path');
const fs = require('fs');

const configPath = path.resolve(process.cwd(), process.argv.slice().pop());
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
const app = express();

async function build (target, args) {
    const commands = args.commands;
    const options = {
        cwd: args.path,
    };

    console.log(`Deploying ${ target }...`);

    for (let i = 0; i < commands.length; i++) {
        const date = (new Date()).toLocaleDateString('sv-SE', {
            hour: 'numeric',
            minute: 'numeric',
            second: 'numeric',
        });

        console.log(`${ date } Running ${ commands[i] }...`);
        await childProcess.exec(commands[i], options);
        console.log('Done');
    }
}

app.post('/', (req, res) => {
    const target = req.query.target;

    if (config.repos[target]) {
        build(target, config.repos[target]);
        res.status(200).send();
    } else {
        res.status(400).send();
    }
});

app.listen(config.port, config.host);

'use strict';

const childProcess = require('child-process-promise');
const express = require('express');
const path = require('path');
const fs = require('fs');

const configPath = path.resolve(process.cwd(), process.argv.slice().pop());
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
const app = express();

async function build (target, args) {
    const commands = args.commands;
    const options = {
        cwd: args.path,
    };

    console.log(`Deploying ${ target }...`);

    for (let i = 0; i < commands.length; i++) {
        const date = (new Date()).toLocaleDateString('sv-SE', {
            hour: 'numeric',
            minute: 'numeric',
            second: 'numeric',
        });

        console.log(`${ date } Running ${ commands[i] }...`);
        await childProcess.exec(commands[i], options);
        console.log('Done');
    }
}

app.post('/', (req, res) => {
    const target = req.query.target;

    if (config.repos[target]) {
        if(req.get('HTTP_X_GITHUB_EVENT') && req.get('HTTP_X_GITHUB_EVENT') === 'push'){
            build(target, config.repos[target]);
            res.status(200).send();
        } else {
            res.status(401).send();
        }
    } else {
        res.status(400).send();
    }
});

app.listen(config.port, config.host);

Add tiny bit of validation to check if the request is a GitHub request or not


import detectIt from 'detect-it';
import addListener from 'the-listener';

function setupCurrentInput() {
  const body = document.querySelector('body');
  let currentInput = undefined;

  function updateCurrentInput(input) {
    if (input !== currentInput) {
      body.classList.remove(`current-input-${currentInput}`);
      body.classList.add(`current-input-${input}`);
      currentInput = input;
    }
  }

  if (detectIt.deviceType === 'mouseOnly') updateCurrentInput('mouse');
  else if (detectIt.deviceType === 'touchOnly') {
    updateCurrentInput('touch');
    // add blank touch listener to body to enable :active state when touching the screen
    addListener(body, { 'touchstart passive capture': () => {} });
  } else {
    // add listeners for hybrid device
    addListener(window,
      {
        'touchstart passive capture': () => { updateCurrentInput('touch'); },
        'mousedown mouseenter mousemove passive capture': () => { updateCurrentInput('mouse'); },
      },
      { pointermove: false }
    );
    /* eslint no-unused-expressions: ["error", { "allowTernary": true }] */
    detectIt.primaryHover === 'hover' ? updateCurrentInput('mouse') : updateCurrentInput('touch');
  }
}

(() => {
  const body = document.querySelector('body');
  if (body) setupCurrentInput();
  else document.addEventListener('DOMContentLoaded', setupCurrentInput);
})();

import detectIt from 'detect-it';
import addListener from 'the-listener';

function setupCurrentInput() {
  const body = document.querySelector('body');
  let currentInput = undefined;

  function updateCurrentInput(input) {
    if (input !== currentInput) {
      body.classList.remove(`current-input-${currentInput}`);
      body.classList.add(`current-input-${input}`);
      currentInput = input;
    }
  }

  if (detectIt.deviceType === 'mouseOnly') updateCurrentInput('mouse');
  else if (detectIt.deviceType === 'touchOnly') {
    updateCurrentInput('touch');
    // add blank touch listener to body to enable :active state when touching the screen
    addListener(body, { 'touchstart passive capture': () => {} });
  } else {
    // add listeners for hybrid device
    addListener(window,
      {
        'touchstart passive capture': () => { updateCurrentInput('touch'); },
        'mousedown mouseenter mousemove passive capture': () => { updateCurrentInput('mouse'); },
      },
      { pointermove: false }
    );
    /* eslint no-unused-expressions: ["error", { "allowTernary": true }] */
    detectIt.primaryHover === 'hover' ? updateCurrentInput('mouse') : updateCurrentInput('touch');
  }

  document.removeEventListener('DOMContentLoaded', setupCurrentInput);
}

(() => {
  const body = document.querySelector('body');
  if (body) setupCurrentInput();
  else document.addEventListener('DOMContentLoaded', setupCurrentInput);
})();

Remove DOMContentLoaded event listener after it's used


import convict from 'convict';
import path from 'path';
import fs from 'fs';

// check and load convict schema
const schemaFile = path.join(process.env.SMART_CONFIG_DIR, 'schema'));
try {
    fs.statSync(schemaFile + '.js'));
} catch (e) {
    throw new Error(`[smart-config] Schema file "${e.path}" does not exists.`);
}
const conf = convict(require(schemaFile));

// check and load related environment config
const configFile = path.join(process.env.SMART_CONFIG_DIR, conf.get('env'));
try {
    fs.statSync(configFile + '.js'));
} catch (e) {
    throw new Error(`[smart-config] Config file "${e.path}" does not exists.`);
}
const envConf = require(configFile);
conf.load(envConf);

// export utility methods and current config properties
export function validate() {
    return conf.validate({ strict: true });
}

export function show() {
    return conf.toString();
}

export default conf.getProperties();

import convict from 'convict';
import path from 'path';
import fs from 'fs';

const configDir = process.env.SMART_CONFIG_DIR;
if (!configDir) {
    throw new Error(`[smart-config] You must configure "SMART_CONFIG_DIR" environment variable`);
}

// check and load convict schema
const schemaFile = path.join(process.env.SMART_CONFIG_DIR, 'schema'));
try {
    fs.statSync(schemaFile + '.js'));
} catch (e) {
    throw new Error(`[smart-config] Schema file "${e.path}" does not exists.`);
}
const conf = convict(require(schemaFile));

// check and load related environment config
const configFile = path.join(process.env.SMART_CONFIG_DIR, conf.get('env'));
try {
    fs.statSync(configFile + '.js'));
} catch (e) {
    throw new Error(`[smart-config] Config file "${e.path}" does not exists.`);
}
const envConf = require(configFile);
conf.load(envConf);

// export utility methods and current config properties
export function validate() {
    return conf.validate({ strict: true });
}

export function show() {
    return conf.toString();
}

export default conf.getProperties();

Check if SMART_CONFIG_DIR env var exists


'use strict'

const callsite = require('sb-callsite')
const nameRegex = /[\\\/]packages[\\\/]([^\\\/]+)[\\\/]/

export function guessFromFilePath(filePath) {
  const matches = nameRegex.exec(filePath)
  return matches ? matches[1] : null
}

export function guess() {
  const filePath = callsite.capture()[2].file
  return guessFromFilePath(filePath)
}

'use strict'

const callsite = require('sb-callsite')
const regexes = [
  /[\\\/]packages[\\\/]([^\\\/]+)[\\\/]/,
  /[\\\/]([\w-_]+)[\\\/](?:lib|src)[\\\/]/,
  /[\\\/]([\w-_]+)[\\\/][\w-_]+\..+$/
]

export function guessFromFilePath(filePath) {
  let matches
  matches = regexes[0].exec(filePath)
  if (matches) {
    return matches[1]
  }
  matches = regexes[1].exec(filePath)
  if (matches) {
    return matches[1]
  }
  matches = regexes[2].exec(filePath)
  if (matches) {
    return matches[1]
  }
  return null
}

export function guess() {
  const filePath = callsite.capture()[2].file
  return guessFromFilePath(filePath)
}

Add support for non-common file paths


import Stack from './stack';
import Card from './card';

export {
    Stack,
    Card
};

import Stack from './stack';
import Card from './card';

global.gajus = global.gajus || {};

global.gajus.Swing = {
    Stack,
    Card
};

export {
    Stack,
    Card
};

Revert "Do not export anything to global environment."


// @flow

// The argument is a full url. The function returns the last two elements of the
// domain.
export const secondLevelDomain = (url:string): string => {
  if (url.startsWith('file:///')) {
    return 'file'
  }
  return url.split('/')[2].split('.').slice(-2).join('.')
}

export const translateHTML = (): void => {
  const elements = document.querySelectorAll('[data-i18n]')
  for (const element of elements) {
    const message = element.getAttribute('data-i18n')
    if (message == null) {
      throw new Error('invalid attribute data-i18n on element ' + element.nodeName)
    }
    element.textContent = browser.i18n.getMessage(message)
  }
}

// @flow

// The argument is a full url. The function returns the last two elements of the
// domain.
export const secondLevelDomain = (url:string): string => {
  // Create a temp a-element to use the api from it
  let element = document.createElement('a')
  element.href = url
  if (element.protocol === 'file:') {
    return 'file'
  }
  return element.hostname.split('.').slice(-2).join('.')
}

export const translateHTML = (): void => {
  const elements = document.querySelectorAll('[data-i18n]')
  for (const element of elements) {
    const message = element.getAttribute('data-i18n')
    if (message == null) {
      throw new Error('invalid attribute data-i18n on element ' + element.nodeName)
    }
    element.textContent = browser.i18n.getMessage(message)
  }
}

Create second level dovument with the html URL interface


#!/usr/bin/env node

var updater = require('update-notifier'),
	pkg     = require('../package.json');

updater({pkg: pkg}).notify();

var yargs = require('yargs')
	.option('registry', {
		description: 'fully-qualified hostname of the registry to use',
		default: 'https://registry.npmjs.org'
	})
	.help('help')
	.version(function() { return require('../package').version; })
	.describe('version', 'show version information')
	.usage('the helpful wombat tool');

var requireDirectory = require('require-directory'),
	commands = requireDirectory(module, '../commands');

Object.keys(commands).forEach(function(c)
{
	var cmd = commands[c];
	yargs.command(cmd);

	if (cmd.aliases)
	{
		cmd.aliases.forEach(function(alias) { yargs.command(alias, false, cmd); });
	}
});

var argv = yargs.argv;

// wombat : npm :: hub : git
if (!argv._handled)
{
	var spawn = require('child_process').spawn;
	var opts = {
		cwd: process.cwd,
		env: process.env,
		stdio: 'inherit',
	};
	var original = process.argv.slice(2);
	spawn('npm', original, opts)
		.on('exit',function(code){ process.exit(code); });
}

#!/usr/bin/env node

var updater = require('update-notifier'),
	pkg     = require('../package.json');

updater({pkg: pkg}).notify();

var yargs = require('yargs')
	.option('registry', {
		description: 'url of the registry to use',
		default: 'https://registry.npmjs.org'
	})
	.help('help')
	.version(function() { return require('../package').version; })
	.describe('version', 'show version information')
	.usage('the helpful wombat tool');

var requireDirectory = require('require-directory'),
	commands = requireDirectory(module, '../commands');

Object.keys(commands).forEach(function(c)
{
	var cmd = commands[c];
	yargs.command(cmd);

	if (cmd.aliases)
	{
		cmd.aliases.forEach(function(alias) { yargs.command(alias, false, cmd); });
	}
});

var argv = yargs.argv;

// wombat : npm :: hub : git
if (!argv._handled)
{
	var spawn = require('child_process').spawn;
	var opts = {
		cwd: process.cwd,
		env: process.env,
		stdio: 'inherit',
	};
	var original = process.argv.slice(2);
	spawn('npm', original, opts)
		.on('exit',function(code){ process.exit(code); });
}

Update help for the registry option, which is now a URI.


Occasion.Modules.push(function(library) {
  library.Order = class Order extends library.Base {};

  library.Order.className = 'Order';
  library.Order.queryName = 'orders';

  library.Order.belongsTo('coupon');
  library.Order.belongsTo('currency');
  library.Order.belongsTo('customer', { autosave: true });
  library.Order.belongsTo('merchant');
  library.Order.belongsTo('product');

  library.Order.hasMany('answers', { autosave: true });
  library.Order.hasMany('timeSlots');
  library.Order.hasMany('transactions', { autosave: true });
});

Occasion.Modules.push(function(library) {
  library.Order = class Order extends library.Base {
    static construct(attributes) {
      var order = this.build(attributes);

      // TODO: Generate session ID
      order.sessionIdentifier = order.sessionIdentifier || '';

      if(order.customer() == null) {
        order.buildCustomer({
          email: null,
          firstName: null,
          lastName: null,
          zip: null
        });
      }

      if(order.product() != null) {
        order.product().questions().each(function(question) {
          order.answers().build({
            question: question
          });
        });
      }
    }
  };

  library.Order.className = 'Order';
  library.Order.queryName = 'orders';

  library.Order.belongsTo('coupon');
  library.Order.belongsTo('currency');
  library.Order.belongsTo('customer', { autosave: true });
  library.Order.belongsTo('merchant');
  library.Order.belongsTo('product');

  library.Order.hasMany('answers', { autosave: true });
  library.Order.hasMany('timeSlots');
  library.Order.hasMany('transactions', { autosave: true });
});

Add Order.construct form helper method


import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import { browserHistory } from 'react-router'
import { syncHistory } from 'react-router-redux'
import { combineReducers, compose, createStore, applyMiddleware } from 'redux'
import { autoRehydrate } from 'redux-persist'
import { analytics, authentication, requester, uploader } from './middleware'
import * as reducers from './reducers'

const reducer = combineReducers(reducers)
const reduxRouterMiddleware = browserHistory ? syncHistory(browserHistory) : null

let store = null
if (typeof window !== 'undefined') {
  const logger = createLogger({ collapsed: true, predicate: () => ENV.APP_DEBUG })
  store = compose(
    autoRehydrate(),
    applyMiddleware(
      thunk,
      authentication,
      reduxRouterMiddleware,
      uploader,
      requester,
      analytics,
      logger
    ),
  )(createStore)(reducer, window.__INITIAL_STATE__ || {})
} else {
  store = compose(
    applyMiddleware(thunk, uploader, requester, analytics),
  )(createStore)(reducer, {})
}

export default store

import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import { browserHistory } from 'react-router'
import { syncHistory } from 'react-router-redux'
import { combineReducers, compose, createStore, applyMiddleware } from 'redux'
import { autoRehydrate } from 'redux-persist'
import { analytics, authentication, requester, uploader } from './middleware'
import * as reducers from './reducers'

const reducer = combineReducers(reducers)
const reduxRouterMiddleware = browserHistory ? syncHistory(browserHistory) : null

let store = null
if (typeof window !== 'undefined') {
  const logger = createLogger({ collapsed: true, predicate: () => ENV.APP_DEBUG })
  store = compose(
    autoRehydrate(),
    applyMiddleware(
      thunk,
      reduxRouterMiddleware,
      uploader,
      requester,
      authentication,
      analytics,
      logger
    ),
  )(createStore)(reducer, window.__INITIAL_STATE__ || {})
} else {
  store = compose(
    applyMiddleware(thunk, uploader, requester, analytics),
  )(createStore)(reducer, {})
}

export default store

Put auth middleware further down the chain


'use strict';

angular.module('core').controller('LastScreenController', ['$scope', 'TrialData', '$http',
    function($scope, TrialData, $http) {
        $http.post('/api/trials', TrialData.data).success(function() {
        }).error(function() {
        });
    }
]);

'use strict';

angular.module('core').controller('LastScreenController', ['$scope', 'TrialData', '$http',
    function($scope, TrialData, $http) {

        // Should chain success() and error() to post() call to log success/error
        $http.post('/api/trials', TrialData.data);
    }
]);

Remove empty calls to success() and error() in LastScreenController


// render modes
export const NO_RENDER = { render: false };
export const SYNC_RENDER = { renderSync: true };
export const DOM_RENDER = { build: true };

export const EMPTY = {};
export const EMPTY_BASE = '';

// is this a DOM environment
export const HAS_DOM = typeof document!=='undefined';
export const TEXT_CONTENT = !HAS_DOM || 'textContent' in document ? 'textContent' : 'nodeValue';

export const ATTR_KEY = '__preactattr_';

export const UNDEFINED_ELEMENT = 'x-undefined-element';

// DOM properties that should NOT have "px" added when numeric
export const NON_DIMENSION_PROPS = {
	boxFlex:1,boxFlexGroup:1,columnCount:1,fillOpacity:1,flex:1,flexGrow:1,
	flexPositive:1,flexShrink:1,flexNegative:1,fontWeight:1,lineClamp:1,lineHeight:1,
	opacity:1,order:1,orphans:1,strokeOpacity:1,widows:1,zIndex:1,zoom:1
};

// render modes
export const NO_RENDER = { render: false };
export const SYNC_RENDER = { renderSync: true };
export const DOM_RENDER = { build: true };

export const EMPTY = {};
export const EMPTY_BASE = '';

// is this a DOM environment
export const HAS_DOM = typeof document!=='undefined';
export const TEXT_CONTENT = !HAS_DOM || 'textContent' in document ? 'textContent' : 'nodeValue';

export const ATTR_KEY = typeof Symbol!=='undefined' ? Symbol('preactattr') : '__preactattr_';

export const UNDEFINED_ELEMENT = 'x-undefined-element';

// DOM properties that should NOT have "px" added when numeric
export const NON_DIMENSION_PROPS = {
	boxFlex:1,boxFlexGroup:1,columnCount:1,fillOpacity:1,flex:1,flexGrow:1,
	flexPositive:1,flexShrink:1,flexNegative:1,fontWeight:1,lineClamp:1,lineHeight:1,
	opacity:1,order:1,orphans:1,strokeOpacity:1,widows:1,zIndex:1,zoom:1
};

Use a Symbol for storing the prop cache where available.


<!-- Google Analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-1687066-2', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1687066-2"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-1687066-2');
</script>

Fix Google Analytics with the recommended snippet


var assert = chai.assert,
    html = React.DOM.html,
    title = React.DOM.title,
    FrozenHead = ReactFrozenHead;

var page = function (pageTitle) {
    return (
        html(null,
            FrozenHead(null,
                title(null, pageTitle)
            )
        )
    );
};

var App = React.createClass({
    getDefaultProps: function () {
        return {title: 'HOME'};
    },
    render: function () {
        return page(this.props.title);
    }
});

describe('react-frozenhead', function () {
    it('renders the initial title', function () {
        var app = App({title: 'INITIAL'}),
            html = React.renderComponentToString(app);
        assert.include(html, '<title>INITIAL</title>');
    });

    it("doesn't update the DOM title after mounting", function (done) {
        var container = document.createElement('div');
            app = React.renderComponent(App({title: 'INITIAL'}), container);
        app.setProps({title: 'NEW'}, function () {
            var titleEl = container.querySelector('title');
            assert.equal(titleEl.text, 'INITIAL');
            done();
        });
    });
});

var assert = chai.assert,
    html = React.DOM.html,
    title = React.DOM.title,
    FrozenHead = ReactFrozenHead;

var page = function (pageTitle) {
    return (
        html(null,
            FrozenHead(null,
                title(null, pageTitle)
            )
        )
    );
};

var App = React.createClass({
    getDefaultProps: function () {
        return {title: 'HOME'};
    },
    render: function () {
        return page(this.props.title);
    }
});

describe('react-frozenhead', function () {
    beforeEach(function () { document.title = 'NONE'; });

    it('renders the initial title', function () {
        var app = App({title: 'INITIAL'}),
            html = React.renderComponentToString(app);
        assert.include(html, '<title>INITIAL</title>');
    });

    it("doesn't update the DOM title after mounting", function (done) {
        var container = document.createElement('div');
            app = React.renderComponent(App({title: 'INITIAL'}), container);
        app.setProps({title: 'NEW'}, function () {
            var titleEl = container.querySelector('title');
            assert.equal(titleEl.text, 'INITIAL');
            done();
        });
    });

    it('changes the page title using document.title after mounting', function (done) {
        var container = document.createElement('div');
            app = React.renderComponent(App({title: 'INITIAL'}), container);
        app.setProps({title: 'NEW'}, function () {
            assert.equal(document.title, 'NEW');
            done();
        });
    });
});

Test that mounted heads change the title correctly


/* eslint-disable no-underscore-dangle */

import PropTypes from 'prop-types';
import { Component } from 'react';
import bootstrap from 'bootstrap';

/**
 * Component that declaratively wraps logic for idempotently bootstrapping the library. Client code
 * can be contained within the children of this component at the highest level of the application.
 */
export default class Elemental extends Component {
  static propTypes = {
    fontOpts: PropTypes.shape({
      primary: PropTypes.shape({
        regular: PropTypes.string,
        bold: PropTypes.string,
      }),
      secondary: PropTypes.shape({
        regular: PropTypes.string,
        bold: PropTypes.string,
      }),
    }),
    colorOpts: PropTypes.shape({
      primary: PropTypes.string,
      primaryLight: PropTypes.string,
      primaryDark: PropTypes.string,
    }),
    children: PropTypes.node.isRequired,
  };

  static defaultProps = {
    fontOpts: {},
    colorOpts: {},
  };

  componentWillMount() {
    const { fontOpts, colorOpts } = this.props;

    // Idempotent bootstrapping by caching initialization state in a global key
    if (!window.__REACT_ELEMENTAL_BOOTSTRAPPED__) {
      bootstrap(fontOpts, colorOpts);

      window.__REACT_ELEMENTAL_BOOTSTRAPPED__ = true;
    }
  }

  render() {
    return this.props.children;
  }
}

/* eslint-disable no-underscore-dangle */

import PropTypes from 'prop-types';
import { Component } from 'react';
import bootstrap from 'bootstrap';

/**
 * Component that declaratively wraps logic for idempotently bootstrapping the library. Client code
 * can be contained within the children of this component at the highest level of the application.
 */
export default class Elemental extends Component {
  static propTypes = {
    fontOpts: PropTypes.shape({
      primary: PropTypes.shape({
        regular: PropTypes.string,
        bold: PropTypes.string,
      }),
      secondary: PropTypes.shape({
        regular: PropTypes.string,
        bold: PropTypes.string,
      }),
    }),
    colorOpts: PropTypes.shape({
      primary: PropTypes.string,
      primaryLight: PropTypes.string,
      primaryDark: PropTypes.string,
    }),
    children: PropTypes.node.isRequired,
  };

  static defaultProps = {
    fontOpts: {},
    colorOpts: {},
  };

  componentDidMount() {
    const { fontOpts, colorOpts } = this.props;

    // Idempotent bootstrapping by caching initialization state in a global key
    if (!window.__REACT_ELEMENTAL_BOOTSTRAPPED__) {
      bootstrap(fontOpts, colorOpts);

      window.__REACT_ELEMENTAL_BOOTSTRAPPED__ = true;
    }
  }

  render() {
    return this.props.children;
  }
}

Migrate away from componentWillMount in declarative bootstrap container


'use strict';

var minimatch = require('minimatch');

module.exports = function(env, callback) {
  function list(contents) {
    var entries = [];

    for (var key in contents._) {
      if (contents._.hasOwnProperty(key)) {
        var value = contents._[key];

        switch (key) {
          case 'directories':
            entries = Array.prototype.concat.apply(entries, value.map(list));
            break;
          default:
            entries = entries.concat(value);
        }
      }
    }

    return entries.sort((a, b) => a.filename.localeCompare(b.filename));
  }

  function filter(contents, pattern) {
    return list(contents).filter((entry) => minimatch(entry.filename, pattern));
  }

  env.helpers.contents = {
    'filter': filter,
    'list': list,
  };

  callback();
};

'use strict';

const minimatch = require('minimatch');

module.exports = function(env, callback) {
  function list(contents) {
    let entries = [];

    for (let key in contents._) {
      if (contents._.hasOwnProperty(key)) {
        const value = contents._[key];

        switch (key) {
          case 'directories':
            entries = Array.prototype.concat.apply(entries, value.map(list));
            break;
          default:
            entries = entries.concat(value);
        }
      }
    }

    return entries.sort((a, b) => a.filename.localeCompare(b.filename));
  }

  function filter(contents, pattern) {
    return list(contents).filter((entry) => minimatch(entry.filename, pattern));
  }

  env.helpers.contents = {
    'filter': filter,
    'list': list,
  };

  callback();
};

Use const and let keywords


console.log('background.js');

config.background = true;

/**
 * Create an app with the config and accounts
 */
app = new App({
  model: config,
  collection: accounts,
});

/**
* Wire events
*/
config.on('ready', app.ready);
accounts.on('ready', app.ready);
config.on('change:frequency', app.changeInterval);
app.on('interval', interactions.checkForNew);
app.on('interval', mentions.checkForNew);
interactions.on('add', interactions.renderNotification);
mentions.on('add', mentions.renderNotification);

/**
 * omnibox events
 */
chrome.omnibox.setDefaultSuggestion({ description: 'Post to App.net <match>%s</match>' });
chrome.omnibox.onInputEntered.addListener(window.omniboxview.onInputEntered);
chrome.omnibox.onInputChanged.addListener(window.omniboxview.onInputChanged);

accounts.on('ready', function() {
  if (accounts.length === 0) {
    var n = new TextNotificationView({
      url: accounts.buildAuthUrl(),
      title: 'Connect your App.net account',
      body: 'Click to connect your App.net account and get started with the awesomeness of Succynct.',
      image: chrome.extension.getURL('/img/angle.png')
    });
    n.render();
  }
});

console.log('background.js');

config.background = true;

/**
 * Create an app with the config and accounts
 */
app = new App({
  model: config,
  collection: accounts,
});

/**
* Wire events
*/
config.on('ready', app.ready, app);
accounts.on('ready', app.ready, app);
config.on('change:frequency', app.changeInterval, app);
app.on('interval', interactions.checkForNew, interactions);
app.on('interval', mentions.checkForNew, mentions);
interactions.on('add', interactions.renderNotification, interactions);
mentions.on('add', mentions.renderNotification, mentions);

/**
 * omnibox events
 */
chrome.omnibox.setDefaultSuggestion({ description: 'Post to App.net <match>%s</match>' });
chrome.omnibox.onInputEntered.addListener(window.omniboxview.onInputEntered);
chrome.omnibox.onInputChanged.addListener(window.omniboxview.onInputChanged);

accounts.on('ready', function() {
  if (accounts.length === 0) {
    var n = new TextNotificationView({
      url: accounts.buildAuthUrl(),
      title: 'Connect your App.net account',
      body: 'Click to connect your App.net account and get started with the awesomeness of Succynct.',
      image: chrome.extension.getURL('/img/angle.png')
    });
    n.render();
  }
});

Send context for on event listeners


let React = require("react")
let cx = require("classnames")
let popup = React.createFactory(require("./timepicker_popup"))
let {errorList, sizeClassNames, formGroupCx, label} = require("../util.js")
let {div, input} = React.DOM

export default class extends React.Component {

  static displayName = "Frig.friggingBootstrap.TimePicker"

  static defaultProps = Object.assign(require("../default_props.js"))

  _input() {
    return input(Object.assign({}, this.props.inputHtml, {
        valueLink: {
          value: this.props.valueLink.value,
          requestChange: this._onTimeChange,
        },
		className: cx(this.props.inputHtml.className, "form-control"),
      })
    )
  }

  _onTimeChange(newTime) {
    console.log(`New Time ${newTime}`)
  }

  render() {
    return div({className: cx(sizeClassNames(this.props))},
      div({className: formGroupCx(this.props)},
        div({},
          label(this.props)
        ),
        this._input(),
        errorList(this.props.errors),
      ),
      popup()
    )
  }

}

let React = require("react")
let cx = require("classnames")
let popup = React.createFactory(require("./timepicker_popup"))
let {errorList, sizeClassNames, formGroupCx, label} = require("../util.js")
let {div, input} = React.DOM

export default class extends React.Component {

  static displayName = "Frig.friggingBootstrap.TimePicker"

  static defaultProps = Object.assign(require("../default_props.js"))

  _input() {
    return input(Object.assign({}, this.props.inputHtml, {
        valueLink: this.props.valueLink,
		className: cx(this.props.inputHtml.className, "form-control"),
      })
    )
  }

  _onTimeChange(newTime) {
    console.log(`New Time ${newTime}`)
  }

  render() {
    return div({className: cx(sizeClassNames(this.props))},
      div({className: formGroupCx(this.props)},
        div({},
          label(this.props)
        ),
        this._input(),
        errorList(this.props.errors),
      ),
      popup({
        valueLink: this.props.valueLink,
      })
    )
  }

}

Update ValueLink To Use Timepicker's ValueLink


module.exports = {
  checkToken (ctx) {
    let requestBody = ctx.request.query
    console.log(requestBody)
    // 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
    let signature = requestBody.signature
    // 时间戳
    let timestamp = requestBody.timestamp
    // 随机数
    let nonce = requestBody.nonce
    // 随机字符串
    let echostr = requestBody.echostr
  }
}

const crypto = require('crypto');
const hash = crypto.createHash('sha1');

module.exports = {
  checkToken (ctx) {
    let requestBody = ctx.request.query
    console.log(requestBody)
    // 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
    let signature = requestBody.signature
    // 时间戳
    let timestamp = requestBody.timestamp
    // 随机数
    let nonce = requestBody.nonce
    // 随机字符串
    let echostr = requestBody.echostr

    let beforeEncrypt = ''
    for (let key of Object.keys(requestBody).sort()) {
      beforeEncrypt += `${key}=${requestBody[key]}`
    }
    hash.update(beforeEncrypt)
    let afterEncrypt = hash.digest('hex')
    if (signature === afterEncrypt) {
      ctx.body = 'Success'
    } else {
      ctx.throw(500)
    }
  }
}

Add logic to check signature.


describe( 'esbeautifier', function () {
  var expand = require( 'glob-expand' );
  var path = require( 'path' );

  var exec = require( '../lib/exec' );
  var read = function ( file ) {
    return require( 'fs' ).readFileSync( file, { encoding: 'utf8' } );
  };

  //var write = require( 'write' ).sync;

  var fs = require( 'fs-extra' );

  fs.removeSync( './tmp' );
  fs.copySync( './resources', './tmp' );

  var files = expand( 'tmp/fixtures/**/*.js' );
  files.forEach( function ( file ) {

    var basename = path.basename( file );

    it( 'should format the file ' + basename + ' and match the expected result', function ( done ) {
      exec( './bin/cli.js --no-use-cache ' + file, { stdio: 'ignore' } ).then( function () {

        var expected = read( path.join( 'tmp/expected/', basename ) );
        var result = read( file );
        //console.log('here >> task complete, result', result, expected);

        expect( result ).to.equal( expected );

        done();
      } ).catch( function ( err ) {
        done( err );
      } );
    } );
  } );

  after( function () { //eslint-disable-line
    //fs.removeSync( './tmp' );
  } );

} );

describe( 'esbeautifier', function () {
  var expand = require( 'glob-expand' );
  var path = require( 'path' );

  var exec = require( '../lib/exec' );
  var read = function ( file ) {
    return require( 'fs' ).readFileSync( file, { encoding: 'utf8' } );
  };

  //var write = require( 'write' ).sync;

  var fs = require( 'fs-extra' );

  fs.removeSync( './tmp' );
  fs.copySync( './resources', './tmp' );

  var files = expand( 'tmp/fixtures/**/*.js' );
  files.forEach( function ( file ) {

    var basename = path.basename( file );

    it( 'should format the file ' + basename + ' and match the expected result', function ( done ) {
      exec( './bin/cli.js --no-use-cache ' + file, { stdio: 'ignore' } ).then( function () {

        var expected = read( path.join( 'tmp/expected/', basename ) );
        var result = read( file );
        //console.log('here >> task complete, result', result, expected);

        expect( result ).to.equal( expected );

        done();
      } ).catch( function ( err ) {
        done( err );
      } );
    } );
  } );

  after( function () { //eslint-disable-line
    fs.removeSync( './tmp' );
  } );

} );

Remove tmp folder at end of tests


var assert = require('assert');
var expect = require('chai').expect;

var Fabric = require('../');
var server = new Fabric.HTTP();

describe('HTTP', function () {
  before(function (done) {
    server.define('Widget', {
      properties: {
        name: { type: String , maxLength: 100 }
      },
      routes: {
        query: '/widgets',
        get: '/widgets/:id'
      }
    });

    server.start(done);
  });

  after(async function () {
    await server.stop();
  });

  it('should expose a constructor', function () {
    assert.equal(typeof Fabric.HTTP, 'function');
  });

  it('can serve a resource', async function () {
    let remote = new Fabric.Remote({
      host: 'localhost:3000'
    });

    let payload = {
      name: 'foobar'
    };

    let vector = new Fabric.Vector(payload);

    vector._sign();

    let result = await remote._POST('/widgets', payload);
    let object = await remote._GET('/widgets');

    assert.equal(result['@id'], vector['@id']);
    assert.equal(object[0]['@id'], vector['@id']);
  });
});

var assert = require('assert');
var expect = require('chai').expect;

var Fabric = require('../');
var server = new Fabric.HTTP();

describe('HTTP', function () {
  before(function (done) {
    server.define('Widget', {
      properties: {
        name: { type: String , maxLength: 100 }
      },
      routes: {
        query: '/widgets',
        get: '/widgets/:id'
      }
    });

    server.start(done);
  });

  after(async function () {
    await server.stop();
  });

  it('should expose a constructor', function () {
    assert.equal(typeof Fabric.HTTP, 'function');
  });

  it('can serve a resource', async function () {
    let remote = new Fabric.Remote({
      host: 'localhost:3000'
    });

    let payload = {
      name: 'foobar'
    };

    let vector = new Fabric.Vector(payload);

    vector._sign();

    let result = await remote._POST('/widgets', payload);
    let object = await remote._GET('/widgets');

    console.log('result:', result);
    console.log('object:', object);

    assert.equal(result['@id'], vector['@id']);
    assert.equal(object[0]['@id'], vector['@id']);
  });
});

Improve logging for HTTP debug mode


var expect = require("expect.js"),
    qrcode = require('./../lib/main'),
    sinon = require("sinon");

describe('in the main module', function() {
    describe("the generate method", function () {
        describe("when not providing a callback", function () {
            beforeEach(function () {
                sinon.stub(console, "log");
            });

            afterEach(function () {
                sinon.sandbox.restore();
                console.log.reset();
            });

            it("logs to the console", function () {
                qrcode.generate("test");
                expect(console.log.called).to.be(true);
            });
        });

        describe("when providing a callback", function () {
            it("will call the callback", function () {
                var cb = sinon.spy();
                qrcode.generate("test", cb);
                expect(cb.called).to.be(true);
            });

            it("will not call the console.log method", function () {
                qrcode.generate("test", sinon.spy());
                expect(console.log.called).to.be(false);
            });
        });

        describe("the QR Code", function () {
            it("should be a string", function (done) {
                qrcode.generate("test", function(result) {
                    expect(result).to.be.a('string');
                    done();
                });
            });

            it("should not end with a newline", function (done) {
                qrcode.generate("test", function(result) {
                    expect(result).not.to.match(/\n$/);
                    done();
                });
            });
        });
    });
});

var expect = require('expect.js'),
    qrcode = require('./../lib/main'),
    sinon = require('sinon');

describe('in the main module', function() {
    describe('the generate method', function () {
        describe('when not providing a callback', function () {
            beforeEach(function () {
                sinon.stub(console, 'log');
            });

            afterEach(function () {
                sinon.sandbox.restore();
                console.log.reset();
            });

            it('logs to the console', function () {
                qrcode.generate('test');
                expect(console.log.called).to.be(true);
            });
        });

        describe('when providing a callback', function () {
            it('will call the callback', function () {
                var cb = sinon.spy();
                qrcode.generate('test', cb);
                expect(cb.called).to.be(true);
            });

            it('will not call the console.log method', function () {
                qrcode.generate('test', sinon.spy());
                expect(console.log.called).to.be(false);
            });
        });

        describe('the QR Code', function () {
            it('should be a string', function (done) {
                qrcode.generate('test', function(result) {
                    expect(result).to.be.a('string');
                    done();
                });
            });

            it('should not end with a newline', function (done) {
                qrcode.generate('test', function(result) {
                    expect(result).not.to.match(/\n$/);
                    done();
                });
            });
        });
    });
});

Use single quotes for consistency.


"use strict";
//handy routines for line-oriented communications protocols
var events=require("events");
var util=require("util");

function LineIO(myconn) //inherits-from...
{
  this.conn=myconn;
  var buffer='';
  var that=this;
  events.EventEmitter.call(this);
  this.conn.on('readable',function () {
    buffer+=that.conn.read();
    var line_end;
    var linecount=0;
    while(buffer.indexOf("\r\n") !== -1) {
      linecount++;
      line_end=buffer.indexOf("\r\n");
      console.warn("FOUND line end at: "+line_end);
      var chunk_to_emit=buffer.substring(0,line_end);
      console.warn("Chunk to emit '"+chunk_to_emit+"'");
      that.emit('line',chunk_to_emit);
      buffer=buffer.slice(line_end+2); //skip past the \r\n
      console.warn("Remaining buffer: '"+buffer+"'");
      if(linecount>10) {
        console.warn("TOO MANY LINES IN ONE PACKET!")
        process.exit();
      }
    }

  });
  this.conn.on('end',function () {
    that.emit("end");
  });
}

util.inherits(LineIO, events.EventEmitter);

LineIO.prototype.write= function (line) {
  this.conn.write(line+"\r\n");
};

LineIO.prototype.end=function () {
  this.conn.end();
};

module.exports=LineIO;

"use strict";
//handy routines for line-oriented communications protocols
var events=require("events");
var util=require("util");

function LineIO(myconn) //inherits-from...
{
  this.conn=myconn;
  var buffer='';
  var that=this;
  events.EventEmitter.call(this);
  var linecount=0;
  var line_end;
  var line_emitter=function () {
    if(buffer.indexOf("\r\n") !== -1) {
      linecount++;
      line_end=buffer.indexOf("\r\n");
      console.warn("FOUND line end at: "+line_end);
      var chunk_to_emit=buffer.substring(0,line_end);
      console.warn("Chunk to emit '"+chunk_to_emit+"'");
      that.emit('line',chunk_to_emit);
      buffer=buffer.slice(line_end+2); //skip past the \r\n
      console.warn("Remaining buffer: '"+buffer+"'");
      process.nextTick(line_emitter);
      if(linecount>10) {
        throw new Error("TOO MANY LINES IN ONE PACKET!")
      }
    }
  };
  this.conn.on('readable',function () {
    buffer+=that.conn.read();
    line_emitter();
  });
  this.conn.on('end',function () {
    that.emit("end");
  });
}

util.inherits(LineIO, events.EventEmitter);

LineIO.prototype.write= function (line) {
  this.conn.write(line+"\r\n");
};

LineIO.prototype.end=function () {
  this.conn.end();
};

module.exports=LineIO;

Change LineIO class to emit via nextTick()


/* ==========================================================================
   Initialize Chosen.js
   ========================================================================== */

$(".chosen-select").chosen({
    width: '100%',
    no_results_text: "Oops, nothing found!"
});

// Reset buttons sould also reset Chosen.js elements
$('.js-form_clear').on('click', function() {
    var $this = $(this),
        $form = $this.parents('form');

    // Reset checkboxes
    $form.find('[type="checkbox"]')
    .removeAttr('checked');

    // Reset select options
    $form.find('select option')
    .removeAttr('selected');
    $form.find('select option:first')
    .attr('selected', true);

    // Reset .custom-input elements
    $form.find('.custom-input').trigger('updateState');

    // Reset Chosen.js elements
    $form.find('.chosen-select')
    .val('')
    .trigger("chosen:updated");
});

/* ==========================================================================
   Initialize Chosen.js
   ========================================================================== */

$(".chosen-select").chosen({
    width: '100%',
    no_results_text: "Oops, nothing found!"
});

/* ==========================================================================
   Clear form button
   - Clear checkboxes and selects
   - Clear Chosen.js elements
   - Clear jquery.custom-input elements
   ========================================================================== */

$('.js-form_clear').on('click', function() {
    var $this = $(this),
        $form = $this.parents('form');

    // Clear checkboxes
    $form.find('[type="checkbox"]')
    .removeAttr('checked');

    // Clear select options
    $form.find('select option')
    .removeAttr('selected');
    $form.find('select option:first')
    .attr('selected', true);

    // Clear .custom-input elements
    $form.find('.custom-input').trigger('updateState');

    // Clear Chosen.js elements
    $form.find('.chosen-select')
    .val('')
    .trigger("chosen:updated");
});

Update comments for form clear button.


/* eslint-env mocha */

const { expect } = require('chai')
const React = require('react')
const Search = require('../js/Search')
const ShowCard = require('../js/ShowCard')
const { shallow } = require('enzyme')
const { shows } = require('../public/data')

describe('<Search />', () => {
  it('should render the brand', () => {
    const wrapper = shallow(<Search />)
    expect(wrapper.contains(
svideo
)).to.be.true
  })

  it('should render as many shows as there are data for', () => {
    const wrapper = shallow(<Search />)
    expect(wrapper.find(ShowCard).length).to.equal(shows.length)
  })
})

/* eslint-env mocha */

const { expect } = require('chai')
const React = require('react')
const Search = require('../js/Search')
const ShowCard = require('../js/ShowCard')
const { shallow, mount } = require('enzyme')
const { shows } = require('../public/data')

describe('<Search />', () => {
  it('should render the brand', () => {
    const wrapper = shallow(<Search />)
    expect(wrapper.contains(
svideo
)).to.be.true
  })

  it('should render as many shows as there are data for', () => {
    const wrapper = shallow(<Search />)
    expect(wrapper.find(ShowCard).length).to.equal(shows.length)
  })

  it('should filter correctly given new state', () => {
    const wrapper = mount(<Search />)
    const input = wrapper.find('.search-input')
    input.node.value = 'house'
    input.simulate('change')
    expect(wrapper.state('searchTerm')).to.equal('house')
    expect(wrapper.find('.show-card').length).to.equal(2)
  })
})

Test for interaction with search using moenzyme mount


var onHeaders = require('on-headers');

module.exports = cacheTagMw;

function cacheTagMw(req, res, next) {
	onHeaders(res, function() {
		if (res.statusCode >= 200 && res.statusCode < 300) {
			var tags = req.get('X-Cache-Tag');
			tags = tags && tags.split(',') || [];
			if (req.method != "GET") tags = tags.map(function(tag) {
				return '+' + tag;
			});
			if (tags.length) res.set('X-Cache-Tag', tags);
		}
	});
	next();
}

var onHeaders = require('on-headers');

module.exports = cacheTagMw;

function cacheTagMw(req, res, next) {
	onHeaders(res, function() {
		if (res.statusCode >= 200 && res.statusCode < 300) {
			var tags = req.get('X-Cache-Tag');
			tags = tags && tags.split(',') || [];
			var rtags = res._headers['x-cache-tag'];
			(rtags && rtags.split(',') || []).forEach(function(tag) {
				if (!~tags.indexOf(tag)) tags.push(tag);
			});

			if (req.method != "GET") tags = tags.map(function(tag) {
				return '+' + tag;
			});
			if (tags.length) res.set('X-Cache-Tag', tags);
		}
	});
	next();
}

Check response headers for tags


import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

xit('renders without crashing', () => {
    const div = document.createElement('div');
    ReactDOM.render(<App />, div);
});

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { shallow } from 'enzyme'

it('renders without crashing', () => {
    const div = document.createElement('div');
    shallow(<App />, div);
});

// TODO: do render test

Test shallow render of <App/>


var os = require('os');

exports.onWindows = function() {
  return os.platform() === 'win32';
}

Fix for os is not defined ReferenceError


(function() {
    'use strict';

    angular.module('Directives')
        .service('dropdownService', dropdownService);

    dropdownService.$inject = ['$rootScope'];

    function dropdownService($rootScope) {
        /* jshint validthis: true */
        var service = this;
        service.cleanSelectedDropdown = cleanSelectedDropdown;
        service.event_selectedModified = event_selectedModified;
        service.on_selectedRoleModified = on_selectedRoleModified;
        service.on_selectedQtySortModified = on_selectedQtySortModified;
        service.on_selectedCategorySearchModified = on_selectedCategorySearchModified;
        service.on_selectedDiscountTypeModified = on_selectedDiscountTypeModified;

        /* ========== Var ========== */
        var configEnum = Object.freeze({
					0: 'SELECTED_ROLE_MODIFIED',
                    1: 'SELECTED_QUANTITY_SORT_MODIFIED',
                    2: 'SELECTED_CATEGORY_SEARCH_MODIFIED',
                    3: 'SELECTED_DISCOUNT_TYPE_MODIFIED'
				});
        service.selectedDropdown = {};

        /* ========== Services ========== */

        /* ========== Public Function ========== */
        function cleanSelectedDropdown() {
            angular.copy({}, service.selectedDropdown);
        }

        function event_selectedModified(arrIndex) {
            $rootScope.$broadcast(configEnum[arrIndex]);
        }

        function on_selectedRoleModified($scope, handler) {
            $scope.$on(configEnum[0], function( /*event*/ ) {
                handler();
            });
        }

        function on_selectedQtySortModified($scope, handler) {
            $scope.$on(configEnum[1], function( /*event*/ ) {
                handler();
            });
        }

        function on_selectedCategorySearchModified($scope, handler) {
            $scope.$on(configEnum[2], function( /*event*/ ) {
                handler();
            });
        }

        function on_selectedDiscountTypeModified($scope, handler) {
            $scope.$on(configEnum[3], function( /*event*/ ) {
                handler();
            });
        }

        /* ========== Private Function ========== */
    }
})();

Clear everything up for sample - didn't save on previous commit


var mercurius = require('../index.js');
var request = require('supertest');
var assert = require('assert');

describe('mercurius', function() {
  before(function() {
    return mercurius.ready;
  });

  it('successfully registers users', function(done) {
    request(mercurius.app)
      .post('/register')
      .send({
        endpoint: 'endpoint',
        key: 'key'
      })
      .expect(function(res) {
        assert.equal(res.status, 200);
        assert.equal(res.text.length, 64);
      })
      .end(done);
  });
});

var mercurius = require('../index.js');
var request = require('supertest');
var assert = require('assert');

describe('mercurius', function() {
  before(function() {
    return mercurius.ready;
  });

  it('successfully registers users', function(done) {
    request(mercurius.app)
      .post('/register')
      .send({
        endpoint: 'endpoint',
        key: 'key'
      })
      .expect(function(res) {
        assert.equal(res.status, 200);
        assert.equal(res.text.length, 64);
      })
      .end(done);
  });

  it('sends 404 when a registration doesn\'t exist', function(done) {
    request(mercurius.app)
      .post('/notify')
      .send({
        token: 'token_inesistente',
      })
      .expect(404, done);
  });
});

Test sending a notification with a token that doesn\'t exist


import Ember from 'ember';
import Authenticator from 'simple-auth-oauth2/authenticators/oauth2';
import ENV from '../config/environment';

export default Authenticator.extend({
    makeRequest: function (url, data) {
        var client_id = ENV['simple-auth']['client-id'];
        var client_secret = ENV['simple-auth']['client-secret'];
        data.grant_type = "password";

        return Ember.$.ajax({
            url: url,
            type: 'POST',
            data: data,
            dataType: 'json',
            contentType: 'application/x-www-form-urlencoded',
            crossDomain: true,
            headers: {
                Authorization: "Basic " + btoa(client_id + ":" + client_secret)
            }
        });
    }
});

import Ember from 'ember';
import Authenticator from 'simple-auth-oauth2/authenticators/oauth2';
import ENV from '../config/environment';

export default Authenticator.extend({
    makeRequest: function (url, data) {
        var client_id = ENV['simple-auth']['client-id'];
        var client_secret = ENV['simple-auth']['client-secret'];

        return Ember.$.ajax({
            url: url,
            type: 'POST',
            data: data,
            dataType: 'json',
            contentType: 'application/x-www-form-urlencoded',
            crossDomain: true,
            headers: {
                Authorization: "Basic " + btoa(client_id + ":" + client_secret)
            }
        });
    }
});

Fix authenticator - refresh was broken


module.exports = {
    duplicateThreshold: 24
}

module.exports = {
    'weboob-installed': 'false',
    'weboob-log': 'no log',
    duplicateThreshold: 24
}

Add default settings for weboob-installed/weboob-log.


import orderPagesBooklet from '../orderPagesBooklet';

const makePage = function () {
  return { element: document.createElement('div') };
};

test('Orders 8', () => {
  const pages = [
    makePage(),
    makePage(),
    makePage(),
    makePage(),
    makePage(),
    makePage(),
    makePage(),
    makePage(),
  ];

  const ordered = orderPagesBooklet(pages, makePage);

  expect(ordered).toEqual([
    // cover
    pages[7],
    pages[0],

    // inside cover
    pages[1],
    pages[6],

    // outside
    pages[5],
    pages[2],

    // inside
    pages[3],
    pages[4],
  ]);
});

test('Adds pages to end when not divisible by 4', () => {
  const pages = [
    makePage(),
    makePage(),
    makePage(),
    makePage(),
    makePage(),
  ];

  const ordered = orderPagesBooklet(pages, makePage);

  expect(ordered.length).toBe(8);
  expect(ordered[1]).toBe(pages[0]);
  expect(ordered[2]).toBe(pages[1]);
  expect(ordered[5]).toBe(pages[2]);
  expect(ordered[6]).toBe(pages[3]);
  expect(ordered[7]).toBe(pages[4]);
});

Test that booklet page count always multiple of 4