<commit_before>/*jshint node: true*/
/**
 * @author lattmann / https://github.com/lattmann
 * @author pmeijer / https://github.com/pmeijer
 */

var path = require('path'),
    config = {
        addOn: {
            enable: false,
            basePaths: [path.join(__dirname, '../src/addon/core')]
        },

        authentication: {
            enable: false,
            allowGuests: true,
            guestAccount: 'guest',
            logOutUrl: '/',
            salts: 10
        },

        bin: {
            log: {
                transports: [{
                    transportType: 'Console',
                    //patterns: ['gme:server:*', '-gme:server:worker*'], // ['gme:server:worker:*'], ['gme:server:*', '-gme:server:worker*']
                    options: {
                        level: 'info',
                        colorize: true,
                        timestamp: true,
                        prettyPrint: true,
                        handleExceptions: true, // ignored by default when you create the logger, see the logger.create function
                        depth: 2
                    }
                }]
            }
        },

        blob: {
            type: 'FS', //'FS', 'S3'
            fsDir: './blob-local-storage',
            s3: {}
        },

        client: {
            appDir: path.join(__dirname, '../src/client'),
            log: {
                level: 'debug' // To see log messages in the browser inspector set:
                               // localStorage.debug = '*' (or 'gme*', 'gme:core*')
            },
            usedDecorators: ['ModelDecorator',
                             'CircleDecorator',
                             'MetaDecorator',
                             'SVGDecorator',
                             'UMLStateMachineDecorator',
                             'DefaultDecorator'],
            // Used in client/WebGME.js to load initial project (if url is specified that has higher priority)
            defaultProject: {
                name: null,   // This is the projectId, e.g. 'guest+TestProject'
                branch: null, // Defaults to master
                node: null    // Defaults to the root-node.
            },
            defaultConnectionRouter: 'basic3' //'basic', 'basic2', 'basic3'
        },

        core: {
            enableCustomConstraints: false,
        },

        debug: false,

        executor: {
            enable: false,
            nonce: null,
            outputDir: './',
            workerRefreshInterval: 5000,
            labelJobs: './labelJobs.json'
        },

        mongo: {
            uri: 'mongodb://127.0.0.1:27017/multi',
            options: {
                db: {
                    w: 1,
                    native_parser: true // jshint ignore: line
                },
                server: {
                    auto_reconnect: true, // jshint ignore: line
                    socketOptions: {keepAlive: 1}
                    //poolSize: 5 // default pool size is 5
                }
            }
        },

        plugin: {
            allowServerExecution: false,
            basePaths: [path.join(__dirname, '../src/plugin/coreplugins')],
            displayAll: false,
            serverResultTimeout: 10000
        },

        requirejsPaths: {},

        rest: {
            secure: false,
            components: {}
        },

        seedProjects: {
            enable: true,
            defaultProject: 'EmptyProject',
            basePaths: [path.join(__dirname, '../seeds')]
        },

        server: {
            port: 8888,
            maxWorkers: 10,
            sessionStore: {
                type: 'Memory', // Memory, Redis, Mongo, options will be passed to the specified storage
                // see specific session store documentations for options connect-mongo and connect-redis
                options: {
                    //url: 'mongodb://127.0.0.1:27017/multi'
                }
            },
            sessionCookieId: 'webgmeSid',
            sessionCookieSecret: 'meWebGMEez',
            log: {
                //patterns: ['gme:server:*', '-gme:server:standalone*'],
                transports: [{
                    transportType: 'Console',
                    //patterns: ['gme:server:*', '-gme:server:worker*'], // ['gme:server:worker:*'], ['gme:server:*', '-gme:server:worker*']
                    options: {
                        level: 'info', // Set this back to info when merged
                        colorize: true,
                        timestamp: true,
                        prettyPrint: true,
                        handleExceptions: true, // ignored by default when you create the logger, see the logger.create function
                        depth: 2
                    }
                }, {
                    transportType: 'File',
                    options: {
                        name: 'info-file',
                        filename: './server.log',
                        level: 'info',
                        json: false
                    }
                }, {
                    transportType: 'File',
                    options: {
                        name: 'error-file',
                        filename: './server-error.log',
                        level: 'error',
                        handleExceptions: true, // ignored by default when you create the logger, see the logger.create function
                        json: false
                    }
                }]
            },
            https: {
                enable: false,
                certificateFile: path.join(__dirname, '../certificates/sample-cert.pem'),
                keyFile: path.join(__dirname, '../certificates/sample-key.pem')
            }
        },

        socketIO: {
            reconnection: true,
            'connect timeout': 10,
            'reconnection delay': 1,
            'force new connection': true
            //transports: ['websocket', 'polling']
        },

        storage: {
            autoPersist: true, // core setting
            cache: 2000,
            // If true events such as PROJECT_CREATED and BRANCH_CREATED will only be broadcasted
            // and not emitted back to the web-socket that triggered the event.
            broadcastProjectEvents: false,
            emitCommittedCoreObjects: false,
            loadBucketSize: 100,
            loadBucketTimer: 10,
            clientCacheSize: 2000, // overwrites cache on client
            keyType: 'plainSHA1' // 'rand160Bits', 'ZSSHA', 'plainSHA1',
        },

        visualization: {
            decoratorPaths: [path.join(__dirname, '../src/client/decorators')],
            visualizerDescriptors: [path.join(__dirname, '../src/client/js/Visualizers.json')]
        }
    };

module.exports = config;
<commit_msg>Fix: add back extlibs to config.<commit_after>/*jshint node: true*/
/**
 * @author lattmann / https://github.com/lattmann
 * @author pmeijer / https://github.com/pmeijer
 */

var path = require('path'),
    config = {
        addOn: {
            enable: false,
            basePaths: [path.join(__dirname, '../src/addon/core')]
        },

        authentication: {
            enable: false,
            allowGuests: true,
            guestAccount: 'guest',
            logOutUrl: '/',
            salts: 10
        },

        bin: {
            log: {
                transports: [{
                    transportType: 'Console',
                    //patterns: ['gme:server:*', '-gme:server:worker*'], // ['gme:server:worker:*'], ['gme:server:*', '-gme:server:worker*']
                    options: {
                        level: 'info',
                        colorize: true,
                        timestamp: true,
                        prettyPrint: true,
                        handleExceptions: true, // ignored by default when you create the logger, see the logger.create function
                        depth: 2
                    }
                }]
            }
        },

        blob: {
            type: 'FS', //'FS', 'S3'
            fsDir: './blob-local-storage',
            s3: {}
        },

        client: {
            appDir: path.join(__dirname, '../src/client'),
            log: {
                level: 'debug' // To see log messages in the browser inspector set:
                               // localStorage.debug = '*' (or 'gme*', 'gme:core*')
            },
            usedDecorators: ['ModelDecorator',
                             'CircleDecorator',
                             'MetaDecorator',
                             'SVGDecorator',
                             'UMLStateMachineDecorator',
                             'DefaultDecorator'],
            // Used in client/WebGME.js to load initial project (if url is specified that has higher priority)
            defaultProject: {
                name: null,   // This is the projectId, e.g. 'guest+TestProject'
                branch: null, // Defaults to master
                node: null    // Defaults to the root-node.
            },
            defaultConnectionRouter: 'basic3' //'basic', 'basic2', 'basic3'
        },

        core: {
            enableCustomConstraints: false,
        },

        debug: false,

        executor: {
            enable: false,
            nonce: null,
            outputDir: './',
            workerRefreshInterval: 5000,
            labelJobs: './labelJobs.json'
        },

        mongo: {
            uri: 'mongodb://127.0.0.1:27017/multi',
            options: {
                db: {
                    w: 1,
                    native_parser: true // jshint ignore: line
                },
                server: {
                    auto_reconnect: true, // jshint ignore: line
                    socketOptions: {keepAlive: 1}
                    //poolSize: 5 // default pool size is 5
                }
            }
        },

        plugin: {
            allowServerExecution: false,
            basePaths: [path.join(__dirname, '../src/plugin/coreplugins')],
            displayAll: false,
            serverResultTimeout: 10000
        },

        requirejsPaths: {},

        rest: {
            secure: false,
            components: {}
        },

        seedProjects: {
            enable: true,
            defaultProject: 'EmptyProject',
            basePaths: [path.join(__dirname, '../seeds')]
        },

        server: {
            port: 8888,
            maxWorkers: 10,
            sessionStore: {
                type: 'Memory', // Memory, Redis, Mongo, options will be passed to the specified storage
                // see specific session store documentations for options connect-mongo and connect-redis
                options: {
                    //url: 'mongodb://127.0.0.1:27017/multi'
                }
            },
            sessionCookieId: 'webgmeSid',
            sessionCookieSecret: 'meWebGMEez',
            log: {
                //patterns: ['gme:server:*', '-gme:server:standalone*'],
                transports: [{
                    transportType: 'Console',
                    //patterns: ['gme:server:*', '-gme:server:worker*'], // ['gme:server:worker:*'], ['gme:server:*', '-gme:server:worker*']
                    options: {
                        level: 'info', // Set this back to info when merged
                        colorize: true,
                        timestamp: true,
                        prettyPrint: true,
                        handleExceptions: true, // ignored by default when you create the logger, see the logger.create function
                        depth: 2
                    }
                }, {
                    transportType: 'File',
                    options: {
                        name: 'info-file',
                        filename: './server.log',
                        level: 'info',
                        json: false
                    }
                }, {
                    transportType: 'File',
                    options: {
                        name: 'error-file',
                        filename: './server-error.log',
                        level: 'error',
                        handleExceptions: true, // ignored by default when you create the logger, see the logger.create function
                        json: false
                    }
                }]
            },
            https: {
                enable: false,
                certificateFile: path.join(__dirname, '../certificates/sample-cert.pem'),
                keyFile: path.join(__dirname, '../certificates/sample-key.pem')
            },
            extlibExcludes: ['.\.pem$', 'config\/config\..*\.js$']
        },

        socketIO: {
            reconnection: true,
            'connect timeout': 10,
            'reconnection delay': 1,
            'force new connection': true
            //transports: ['websocket', 'polling']
        },

        storage: {
            autoPersist: true, // core setting
            cache: 2000,
            // If true events such as PROJECT_CREATED and BRANCH_CREATED will only be broadcasted
            // and not emitted back to the web-socket that triggered the event.
            broadcastProjectEvents: false,
            emitCommittedCoreObjects: false,
            loadBucketSize: 100,
            loadBucketTimer: 10,
            clientCacheSize: 2000, // overwrites cache on client
            keyType: 'plainSHA1' // 'rand160Bits', 'ZSSHA', 'plainSHA1',
        },

        visualization: {
            decoratorPaths: [path.join(__dirname, '../src/client/decorators')],
            visualizerDescriptors: [path.join(__dirname, '../src/client/js/Visualizers.json')]
        }
    };

module.exports = config;
<|endoftext|>


<commit_before>/*jshint onevar:false*/

var Path = require('path'),
    fs = require('fs'),
    relationLabelByType = {
        HtmlScript: '<script>',
        HtmlJsx: 'text/jsx',
        HtmlDart: 'application/dart',
        HtmlStyle: '<style>',
        HtmlCacheManifest: '<html manifest>',
        HtmlIFrame: '<iframe>',
        HtmlFrame: '<frame>',
        HtmlTemplate: '<template>',
        HtmlAlternateLink: '<link rel=alternate>',
        HtmlImport: '<link rel=import>',
        HtmlConditionalComment: function (htmlConditionalComment) {return '<!--[if ' + htmlConditionalComment.condition + ']>'; },
        HtmlImage: '<img>',
        HtmlAudio: '<audio>',
        HtmlShortcutIcon: 'icon',
        HtmlVideo: '<video>',
        HtmlVideoPoster: '<video poster>',
        HtmlEmbed: '<embed>',
        HtmlApplet: '<applet>',
        HtmlObject: '<object>',
        HtmlEdgeSideInclude: '<esi:include>',
        HtmlAnchor: '<a>',
        HtmlRequireJsMain: 'data-main',
        HtmlRequireJsAlmondReplacement: 'data-almond',
        JavaScriptInclude: 'INCLUDE',
        JavaScriptGetText: 'GETTEXT',
        JavaScriptGetStaticUrl: 'GETSTATICURL',
        JavaScriptAmdDefine: 'define',
        JavaScriptAmdRequire: 'require',
        CssImage: 'background-image',
        CssImport: '@import',
        CssBehavior: 'behavior',
        CssFontFaceSrc: '@font-face src',
        CssAlphaImageLoader: 'AlphaImageLoader'
    };

function hasOutgoingRelationToNonInlineAsset(asset) {
    var hasOutgoingRelations = false,
        outgoingRelations = asset.outgoingRelations;
    for (var i = 0 ; i < outgoingRelations.length ; i +=1 ) {
        var outgoingRelation = outgoingRelations[i];
        if (outgoingRelation.to.isLoaded && outgoingRelation.to.url && outgoingRelation.to.isAsset) {
            return true;
        } else if (outgoingRelation.to.isLoaded && hasOutgoingRelationToNonInlineAsset(outgoingRelation.to)) {
            return true;
        }
    }
    return false;
}

module.exports = function (config) {
    config = config || {};
    var targetFileName = config.fileName || 'assetviz.html',
        verbose = config.verbose,
        data = {
            assets: [],
            relations: []
        };

    return function assetviz(assetGraph, cb) {
        var idx = 0,
            vizGraph = new assetGraph.constructor({ root: Path.normalize(Path.dirname(module.filename) + '/tpl/') }),
            query = assetGraph.constructor.query;

        assetGraph.findAssets().forEach(function (asset) {
            if (verbose || asset.url ||hasOutgoingRelationToNonInlineAsset(asset)) {
                asset.idx = idx;
                var size = 400;
                if (asset.url && asset.isLoaded) {
                    size = asset.rawSrc.length;
                }
                data.assets.push({
                    path: asset.url ? Path.relative(assetGraph.root, asset.url) : '',
                    fileName: (asset.url ? Path.basename(asset.url) : 'i:' + asset).replace(/"/g, '\\"'),
                    type: asset.type.toLowerCase(),
                    size: size,
                    r: 3 + Math.sqrt(size / 100),
                    outgoing: 0,
                    initial: asset.isInitial
                });
                idx += 1;
            }
        });

        assetGraph.findRelations().forEach(function (relation) {
            if (verbose || ('idx' in relation.from && 'idx' in relation.to)) {
                var typeString = relationLabelByType[relation.type] || '';
                if (typeof typeString === 'function') {
                    typeString = typeString(relation);
                }
                data.assets[relation.from.idx].outgoing += 1;
                data.relations.push({
                    source: relation.from.idx,
                    target: relation.to.idx,
                    type: typeString
                });
            }
        });

        var dataString = 'var assetgraph = ' + JSON.stringify(data, undefined, 4);

        // Protection against browser misinterpretation of tags in content
        dataString = dataString.replace(/"</g, '"<"+"');

        vizGraph.on('error', function (err) {
                console.error((err.asset ? err.asset.urlOrDescription + ': ' : '') + err.stack);
                process.exit(1);
            })
            .loadAssets([
                'index.html'
            ])
            .populate({
                followRelations: {
                    type: query.not(['HtmlAnchor'])
                }
            })
            .queue(function injectAssetData(assetGraph) {
                assetGraph.findAssets({
                    type: 'JavaScript',
                    fileName: 'data.js'
                })[0].text = dataString;
            })
            .inlineRelations({
                type: ['CssImage', 'HtmlImage', 'HtmlShortcutIcon', 'HtmlAppleTouchStartupImage']
            })
            .inlineRelations({
                type: ['CssFontFaceSrc']
            })
            .inlineRelations({
                type: ['CssBehavior']
            })
            /*
            .compressJavaScript({type: 'JavaScript'}, 'uglifyJs')
            .minifyAssets({
                type: ['Html', 'JavaScript', 'Css']
            })
            */
            // inline style and script
            .inlineRelations({ type: ['HtmlStyle', 'HtmlScript'] })
            .if(targetFileName !== '-')
                .moveAssets({type: 'Html', isInline: false}, function (asset) {
                return "file://" + Path.normalize(targetFileName);
            })
                .writeAssetsToDisc({url: /^file:/})
                .queue(function () {
                    console.warn('Output written to: ' + targetFileName);
                })
            .endif()
            .if(targetFileName === '-')
                .queue(function (assetGraph) {
                    console.log(assetGraph.findAssets({type: 'Html', isInline: false})[0].text);
                })
            .endif()
            .run(function (err) {
                if (err) {
                    console.error(err);
                }
            });

        cb();
    };
};
<commit_msg>Linting<commit_after>/*jshint onevar:false*/

var Path = require('path'),
    relationLabelByType = {
        HtmlScript: '<script>',
        HtmlJsx: 'text/jsx',
        HtmlDart: 'application/dart',
        HtmlStyle: '<style>',
        HtmlCacheManifest: '<html manifest>',
        HtmlIFrame: '<iframe>',
        HtmlFrame: '<frame>',
        HtmlTemplate: '<template>',
        HtmlAlternateLink: '<link rel=alternate>',
        HtmlImport: '<link rel=import>',
        HtmlConditionalComment: function (htmlConditionalComment) {return '<!--[if ' + htmlConditionalComment.condition + ']>'; },
        HtmlImage: '<img>',
        HtmlAudio: '<audio>',
        HtmlShortcutIcon: 'icon',
        HtmlVideo: '<video>',
        HtmlVideoPoster: '<video poster>',
        HtmlEmbed: '<embed>',
        HtmlApplet: '<applet>',
        HtmlObject: '<object>',
        HtmlEdgeSideInclude: '<esi:include>',
        HtmlAnchor: '<a>',
        HtmlRequireJsMain: 'data-main',
        HtmlRequireJsAlmondReplacement: 'data-almond',
        JavaScriptInclude: 'INCLUDE',
        JavaScriptGetText: 'GETTEXT',
        JavaScriptGetStaticUrl: 'GETSTATICURL',
        JavaScriptAmdDefine: 'define',
        JavaScriptAmdRequire: 'require',
        CssImage: 'background-image',
        CssImport: '@import',
        CssBehavior: 'behavior',
        CssFontFaceSrc: '@font-face src',
        CssAlphaImageLoader: 'AlphaImageLoader'
    };

function hasOutgoingRelationToNonInlineAsset(asset) {
    var outgoingRelations = asset.outgoingRelations;
    for (var i = 0 ; i < outgoingRelations.length ; i += 1) {
        var outgoingRelation = outgoingRelations[i];
        if (outgoingRelation.to.isLoaded && outgoingRelation.to.url && outgoingRelation.to.isAsset) {
            return true;
        } else if (outgoingRelation.to.isLoaded && hasOutgoingRelationToNonInlineAsset(outgoingRelation.to)) {
            return true;
        }
    }
    return false;
}

module.exports = function (config) {
    config = config || {};
    var targetFileName = config.fileName || 'assetviz.html',
        verbose = config.verbose,
        data = {
            assets: [],
            relations: []
        };

    return function assetviz(assetGraph, cb) {
        var idx = 0,
            vizGraph = new assetGraph.constructor({ root: Path.normalize(Path.dirname(module.filename) + '/tpl/') }),
            query = assetGraph.constructor.query;

        assetGraph.findAssets().forEach(function (asset) {
            if (verbose || asset.url || hasOutgoingRelationToNonInlineAsset(asset)) {
                asset.idx = idx;
                var size = 400;
                if (asset.url && asset.isLoaded) {
                    size = asset.rawSrc.length;
                }
                data.assets.push({
                    path: asset.url ? Path.relative(assetGraph.root, asset.url) : '',
                    fileName: (asset.url ? Path.basename(asset.url) : 'i:' + asset).replace(/"/g, '\\"'),
                    type: asset.type.toLowerCase(),
                    size: size,
                    r: 3 + Math.sqrt(size / 100),
                    outgoing: 0,
                    initial: asset.isInitial
                });
                idx += 1;
            }
        });

        assetGraph.findRelations(undefined, true).forEach(function (relation) {
            if (verbose || ('idx' in relation.from && 'idx' in relation.to)) {
                var typeString = relationLabelByType[relation.type] || '';
                if (typeof typeString === 'function') {
                    typeString = typeString(relation);
                }
                data.assets[relation.from.idx].outgoing += 1;
                data.relations.push({
                    source: relation.from.idx,
                    target: relation.to.idx,
                    type: typeString
                });
            }
        });

        var dataString = 'var assetgraph = ' + JSON.stringify(data, undefined, 4);

        // Protection against browser misinterpretation of tags in content
        dataString = dataString.replace(/"</g, '"<"+"');

        vizGraph.on('error', function (err) {
                console.error((err.asset ? err.asset.urlOrDescription + ': ' : '') + err.stack);
                process.exit(1);
            })
            .loadAssets([
                'index.html'
            ])
            .populate({
                followRelations: {
                    type: query.not(['HtmlAnchor'])
                }
            })
            .queue(function injectAssetData(assetGraph) {
                assetGraph.findAssets({
                    type: 'JavaScript',
                    fileName: 'data.js'
                })[0].text = dataString;
            })
            .inlineRelations({
                type: ['CssImage', 'HtmlImage', 'HtmlShortcutIcon', 'HtmlAppleTouchStartupImage']
            })
            .inlineRelations({
                type: ['CssFontFaceSrc']
            })
            .inlineRelations({
                type: ['CssBehavior']
            })
            /*
            .compressJavaScript({type: 'JavaScript'}, 'uglifyJs')
            .minifyAssets({
                type: ['Html', 'JavaScript', 'Css']
            })
            */
            // inline style and script
            .inlineRelations({ type: ['HtmlStyle', 'HtmlScript'] })
            .if(targetFileName !== '-')
                .moveAssets({type: 'Html', isInline: false}, function () {
                    return 'file://' + Path.normalize(targetFileName);
                })
                .writeAssetsToDisc({url: /^file:/})
                .queue(function () {
                    console.warn('Output written to: ' + targetFileName);
                })
            .endif()
            .if(targetFileName === '-')
                .queue(function (assetGraph) {
                    console.log(assetGraph.findAssets({type: 'Html', isInline: false})[0].text);
                })
            .endif()
            .run(function (err) {
                if (err) {
                    console.error(err);
                }
            });

        cb();
    };
};
<|endoftext|>


<commit_before>var
  should = require('should'),
  Kuzzle = require('../../../src/Kuzzle'),
  User = require('../../../src/security/User'),
  sinon = require('sinon');

describe('Security user methods', function () {
  var
    kuzzle,
    expectedQuery,
    result;

  beforeEach(function () {
    kuzzle = new Kuzzle('foo', {connect: 'manual'});
    kuzzle.query = sinon.stub();
  });

  describe('#fetchUser', function () {
    beforeEach(function () {
      result = { result: {_id: 'foobar', _source: {profileIds: ['profile']}}};
      expectedQuery = {
        action: 'getUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      kuzzle.security.fetchUser('foobar', function (err, res) {
        should(err).be.null();
        should(res).be.instanceof(User);

        should(res.content.profileIds).be.an.Array();
        should(res.content.profileIds[0]).be.a.String();
        should(res.content.profileIds[0]).be.exactly('profile');

        done();
      });

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).be.calledWith(expectedQuery, {_id: 'foobar'}, null, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should raise an error if no callback is provided', function () {
      should(function () { kuzzle.security.fetchUser('test'); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should throw an error when no id is provided', function () {
      should(function () { kuzzle.security.fetchUser(null, function () {}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.fetchUser('foobar', function (err, res) {
        should(err).be.exactly('error');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('error');
    });
  });

  describe('#searchUsers', function () {
    beforeEach(function () {
      result = { result: { total: 123, hits: [ {_id: 'foobar', _source: {profileIds : ['myProfile']}} ]}};
      expectedQuery = {
        action: 'searchUsers',
        controller: 'security'
      };
    });

    it('should send the right search query to kuzzle and return user with string', function (done) {
      var
        options = {opt: 'val'},
        filters = {foo: 'bar'};

      this.timeout(50);

      should(kuzzle.security.searchUsers(filters, options, function (err, res) {
        should(err).be.null();
        should(res).be.an.Object();
        should(res.total).be.a.Number().and.be.exactly(123);
        should(res.users).be.an.Array();
        should(res.users).not.be.empty();
        should(res.users.length).be.exactly(1);

        res.users.forEach(function (item) {
          should(item).be.instanceof(User);

          should(item.id).be.exactly('foobar');

          should(item.content.profileIds).be.an.Array();
          should(item.content.profileIds[0]).be.a.String();
          should(item.content.profileIds[0]).be.exactly('myProfile');
        });

        done();
      }));

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).be.calledWith(expectedQuery, {body: filters}, options, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should raise an error if no callback is provided', function () {
      should(function () { kuzzle.security.searchUsers({}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.searchUsers({}, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#createUser', function () {
    var content = {profileIds: ['myProfile']};

    beforeEach(function () {
      kuzzle.security.fetchUser = sinon.stub();
      result = { result: {_id: 'foobar', _source: content}};
      expectedQuery = {
        action: 'createUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      should(kuzzle.security.createUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.instanceof(User);
        done();
      }));
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.createUser('foobar', content);
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, undefined);
    });

    it('should throw an error if no id provided', function () {
      should(function () { kuzzle.security.createUser(null); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.createUser(result.result._id, result.result._source, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#createRestrictedUser', function () {
    var content = {some: 'body'};

    beforeEach(function () {
      result = {result: {_id: 'foobar', _source: content}};
      expectedQuery = {
        action: 'createRestrictedUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      kuzzle.security.createRestrictedUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.instanceof(User);
        done();
      });

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);
      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.createRestrictedUser('foobar', content);
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, undefined);
    });

    it('should throw an error if no id provided', function () {
      should(function () { kuzzle.security.createRestrictedUser(null); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should throw an error if profileIds is provided', function () {
      should(function () { kuzzle.security.createRestrictedUser('foobar', {profileIds: ['someProfile']}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.createRestrictedUser(result.result._id, result.result._source, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#replaceUser', function () {
    var content = {profileIds: ['foobar']};

    beforeEach(function () {
      result = { result: {_id: 'foobar', _index: '%kuzzle', _type: 'users', _source: content}};
      expectedQuery = {
        action: 'replaceUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function(done) {
      kuzzle.security.replaceUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.instanceOf(User);
        should(res).containDeep(new User(kuzzle.security, result.result._id, result.result._source));
        done();
      });

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.replaceUser('foobar', {'foo': 'bar'});
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {foo: 'bar'}}, undefined, undefined);
    });

    it('should throw an error if no id is provided', function () {
      should(function () { kuzzle.security.replaceUser(null, {'foo': 'bar'}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });
  });

  describe('#updateUser', function () {
    var content = {profileIds: ['foobar']};

    beforeEach(function () {
      result = { result: {_id: 'foobar', _index: '%kuzzle', _type: 'users', _source: content}};
      expectedQuery = {
        action: 'updateUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      should(kuzzle.security.updateUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.an.instanceOf(User);
        should(res).containDeep(new User(kuzzle.security, 'foobar', content));
        done();
      }));

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);
      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.updateUser('foobar', {'foo': 'bar'});
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {foo: 'bar'}}, undefined, undefined);
    });

    it('should throw an error if no id provided', function () {
      should(function () { kuzzle.security.updateUser(null); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.updateUser(result.result._id, {'foo': 'bar'}, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#deleteUser', function () {
    beforeEach(function () {
      result = { result: {_id: 'foobar'} };
      expectedQuery = {
        action: 'deleteUser',
        controller: 'security'
      };
    });

    it('should send the right delete query to Kuzzle', function (done) {
      this.timeout(50);

      should(kuzzle.security.deleteUser('foobar', function (err, res) {
        should(err).be.null();
        should(res).be.exactly('foobar');
        done();
      }));

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar'}, null, sinon.match.func);
      kuzzle.query.yield(null, result);
    });

    it('should send the right delete query to Kuzzle even without callback', function () {
      kuzzle.security.deleteUser('foobar');
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar'}, undefined, undefined);
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.deleteUser(result.result._id, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#UserFactory', function () {
    it('should return an instance of User', function () {
      var user = kuzzle.security.user('test', {profileIds: ['myProfile']});
      should(user).instanceof(User);
      should(user.content.profileIds).be.an.Array();
      should(user.content.profileIds.length).be.exactly(1);
      should(user.content.profileIds[0]).be.exactly('myProfile');
    });

    it('should throw an error if no id is provided', function () {
      should((function () {kuzzle.security.user(null);})).throw(Error);
    });
  });
});
<commit_msg>Adapt tests<commit_after>var
  should = require('should'),
  Kuzzle = require('../../../src/Kuzzle'),
  User = require('../../../src/security/User'),
  sinon = require('sinon');

describe('Security user methods', function () {
  var
    kuzzle,
    expectedQuery,
    result;

  beforeEach(function () {
    kuzzle = new Kuzzle('foo', {connect: 'manual'});
    kuzzle.query = sinon.stub();
  });

  describe('#fetchUser', function () {
    beforeEach(function () {
      result = { result: {_id: 'foobar', _source: {profileIds: ['profile']}}};
      expectedQuery = {
        action: 'getUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      kuzzle.security.fetchUser('foobar', function (err, res) {
        should(err).be.null();
        should(res).be.instanceof(User);

        should(res.content.profileIds).be.an.Array();
        should(res.content.profileIds[0]).be.a.String();
        should(res.content.profileIds[0]).be.exactly('profile');

        done();
      });

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).be.calledWith(expectedQuery, {_id: 'foobar'}, null, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should raise an error if no callback is provided', function () {
      should(function () { kuzzle.security.fetchUser('test'); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should throw an error when no id is provided', function () {
      should(function () { kuzzle.security.fetchUser(null, function () {}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.fetchUser('foobar', function (err, res) {
        should(err).be.exactly('error');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('error');
    });
  });

  describe('#searchUsers', function () {
    beforeEach(function () {
      result = { result: { total: 123, hits: [ {_id: 'foobar', _source: {profileIds : ['myProfile']}} ]}};
      expectedQuery = {
        action: 'searchUsers',
        controller: 'security'
      };
    });

    it('should send the right search query to kuzzle and return user with string', function (done) {
      var
        options = {opt: 'val'},
        filters = {foo: 'bar'};

      this.timeout(50);

      should(kuzzle.security.searchUsers(filters, options, function (err, res) {
        should(err).be.null();
        should(res).be.an.Object();
        should(res.total).be.a.Number().and.be.exactly(123);
        should(res.users).be.an.Array();
        should(res.users).not.be.empty();
        should(res.users.length).be.exactly(1);

        res.users.forEach(function (item) {
          should(item).be.instanceof(User);

          should(item.id).be.exactly('foobar');

          should(item.content.profileIds).be.an.Array();
          should(item.content.profileIds[0]).be.a.String();
          should(item.content.profileIds[0]).be.exactly('myProfile');
        });

        done();
      }));

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).be.calledWith(expectedQuery, {body: filters}, options, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should raise an error if no callback is provided', function () {
      should(function () { kuzzle.security.searchUsers({}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.searchUsers({}, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#createUser', function () {
    var content = {profileIds: ['myProfile']};

    beforeEach(function () {
      kuzzle.security.fetchUser = sinon.stub();
      result = { result: {_id: 'foobar', _source: content}};
      expectedQuery = {
        action: 'createUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      should(kuzzle.security.createUser('foobar', {content: content, credentials: {some: 'credentials'}}, function (err, res) {
        should(err).be.null();
        should(res).be.instanceof(User);
        done();
      }));
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {content: content, credentials: {some: 'credentials'}}}, null, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.createUser('foobar', content);
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, undefined);
    });

    it('should throw an error if no id provided', function () {
      should(function () { kuzzle.security.createUser(null); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.createUser(result.result._id, result.result._source, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#createRestrictedUser', function () {
    var content = {some: 'body'};

    beforeEach(function () {
      result = {result: {_id: 'foobar', _source: content}};
      expectedQuery = {
        action: 'createRestrictedUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      kuzzle.security.createRestrictedUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.instanceof(User);
        done();
      });

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);
      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.createRestrictedUser('foobar', content);
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, undefined);
    });

    it('should throw an error if no id provided', function () {
      should(function () { kuzzle.security.createRestrictedUser(null); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should throw an error if profileIds is provided', function () {
      should(function () { kuzzle.security.createRestrictedUser('foobar', {profileIds: ['someProfile']}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.createRestrictedUser(result.result._id, result.result._source, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#replaceUser', function () {
    var content = {profileIds: ['foobar']};

    beforeEach(function () {
      result = { result: {_id: 'foobar', _index: '%kuzzle', _type: 'users', _source: content}};
      expectedQuery = {
        action: 'replaceUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function(done) {
      kuzzle.security.replaceUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.instanceOf(User);
        should(res).containDeep(new User(kuzzle.security, result.result._id, result.result._source));
        done();
      });

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);

      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.replaceUser('foobar', {'foo': 'bar'});
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {foo: 'bar'}}, undefined, undefined);
    });

    it('should throw an error if no id is provided', function () {
      should(function () { kuzzle.security.replaceUser(null, {'foo': 'bar'}); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });
  });

  describe('#updateUser', function () {
    var content = {profileIds: ['foobar']};

    beforeEach(function () {
      result = { result: {_id: 'foobar', _index: '%kuzzle', _type: 'users', _source: content}};
      expectedQuery = {
        action: 'updateUser',
        controller: 'security'
      };
    });

    it('should send the right query to Kuzzle', function (done) {
      this.timeout(50);

      should(kuzzle.security.updateUser('foobar', content, function (err, res) {
        should(err).be.null();
        should(res).be.an.instanceOf(User);
        should(res).containDeep(new User(kuzzle.security, 'foobar', content));
        done();
      }));

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: content}, null, sinon.match.func);
      kuzzle.query.yield(null, result);
    });

    it('should send the right query to Kuzzle even without callback', function () {
      kuzzle.security.updateUser('foobar', {'foo': 'bar'});
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar', body: {foo: 'bar'}}, undefined, undefined);
    });

    it('should throw an error if no id provided', function () {
      should(function () { kuzzle.security.updateUser(null); }).throw(Error);
      should(kuzzle.query).not.be.called();
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.updateUser(result.result._id, {'foo': 'bar'}, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#deleteUser', function () {
    beforeEach(function () {
      result = { result: {_id: 'foobar'} };
      expectedQuery = {
        action: 'deleteUser',
        controller: 'security'
      };
    });

    it('should send the right delete query to Kuzzle', function (done) {
      this.timeout(50);

      should(kuzzle.security.deleteUser('foobar', function (err, res) {
        should(err).be.null();
        should(res).be.exactly('foobar');
        done();
      }));

      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar'}, null, sinon.match.func);
      kuzzle.query.yield(null, result);
    });

    it('should send the right delete query to Kuzzle even without callback', function () {
      kuzzle.security.deleteUser('foobar');
      should(kuzzle.query).be.calledOnce();
      should(kuzzle.query).calledWith(expectedQuery, {_id: 'foobar'}, undefined, undefined);
    });

    it('should call the callback with an error if one occurs', function (done) {
      this.timeout(50);

      kuzzle.security.deleteUser(result.result._id, function (err, res) {
        should(err).be.exactly('foobar');
        should(res).be.undefined();
        done();
      });

      kuzzle.query.yield('foobar');
    });
  });

  describe('#UserFactory', function () {
    it('should return an instance of User', function () {
      var user = kuzzle.security.user('test', {profileIds: ['myProfile']});
      should(user).instanceof(User);
      should(user.content.profileIds).be.an.Array();
      should(user.content.profileIds.length).be.exactly(1);
      should(user.content.profileIds[0]).be.exactly('myProfile');
    });

    it('should throw an error if no id is provided', function () {
      should((function () {kuzzle.security.user(null);})).throw(Error);
    });
  });
});
<|endoftext|>


<commit_before>var assign = require('object-assign');
var babel = require('babel-core');
var cache = require('./lib/fs-cache.js');
var loaderUtils = require('loader-utils');
var pkg = require('./package.json');

var transpile = function(source, options) {
  var result = babel.transform(source, options);
  var code = result.code;
  var map = result.map;

  if (map) {
    map.sourcesContent = [source];
  }

  return {
    code: code,
    map: map,
  };
};

module.exports = function(source, inputSourceMap) {
  var callback = this.async();
  var result = {};
  // Handle options
  var defaultOptions = {
    inputSourceMap: inputSourceMap,
    filename: loaderUtils.getRemainingRequest(this),
    cacheIdentifier: JSON.stringify({
      'babel-loader': pkg.version,
      'babel-core': babel.version,
    }),
  };
  var globalOptions = this.options.babel;
  var loaderOptions = loaderUtils.parseQuery(this.query);
  var options = assign({}, defaultOptions, globalOptions, loaderOptions);

  if (options.sourceMap === undefined) {
    options.sourceMap = this.sourceMap;
  }

  cacheDirectory = options.cacheDirectory;
  cacheIdentifier = options.cacheIdentifier;

  delete options.cacheDirectory;
  delete options.cacheIdentifier;

  this.cacheable();

  if (cacheDirectory) {
    return cache({
      directory: cacheDirectory,
      identifier: cacheIdentifier,
      source: source,
      options: options,
      transform: transpile,
    }, function(err, result) {
      if (err) { return callback(err); }
      return callback(null, result.code, result.map);
    });
  }

  result = transpile(source, options);
  return callback(null, result.code, result.map);

};
<commit_msg>Fix #74<commit_after>'use strict';

var assign = require('object-assign');
var babel = require('babel-core');
var cache = require('./lib/fs-cache.js');
var loaderUtils = require('loader-utils');
var pkg = require('./package.json');

var transpile = function(source, options) {
  var result = babel.transform(source, options);
  var code = result.code;
  var map = result.map;

  if (map) {
    map.sourcesContent = [source];
  }

  return {
    code: code,
    map: map,
  };
};

module.exports = function(source, inputSourceMap) {
  var callback = this.async();
  var result = {};
  // Handle options
  var defaultOptions = {
    inputSourceMap: inputSourceMap,
    filename: loaderUtils.getRemainingRequest(this),
    cacheIdentifier: JSON.stringify({
      'babel-loader': pkg.version,
      'babel-core': babel.version,
    }),
  };
  var globalOptions = this.options.babel;
  var loaderOptions = loaderUtils.parseQuery(this.query);
  var options = assign({}, defaultOptions, globalOptions, loaderOptions);

  if (options.sourceMap === undefined) {
    options.sourceMap = this.sourceMap;
  }

  var cacheDirectory = options.cacheDirectory;
  var cacheIdentifier = options.cacheIdentifier;

  delete options.cacheDirectory;
  delete options.cacheIdentifier;

  this.cacheable();

  if (cacheDirectory) {
    return cache({
      directory: cacheDirectory,
      identifier: cacheIdentifier,
      source: source,
      options: options,
      transform: transpile,
    }, function(err, result) {
      if (err) { return callback(err); }
      return callback(null, result.code, result.map);
    });
  }

  result = transpile(source, options);
  return callback(null, result.code, result.map);

};
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var swig = require('swig');
var ical = require('ical');
var moment = require('moment');

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

var url = 'https://www.google.com/calendar/ical/5lbbqnn4nejdarbi983749jv10%40group.calendar.google.com/public/basic.ics';

app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/templates');
app.set('view cache', false);
swig.setDefaults({ cache: false });

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

app.get('/', function (req, res) {

	var days = {};
	var next = moment();
	var end = next.clone().add(1, 'months');
	while (next <= end) {
		var currentDate = next.clone();
		days[currentDate.format('YYYY-MM-DD')] = {
			moment: currentDate
		};
		next.add(1, 'days');
	}

	ical.fromURL(url, {}, function(err, data) {
		for (var k in data) {
			if (data.hasOwnProperty(k)) {
				var ev = data[k];
				var startMoment = moment(ev.start);
				var endMoment = moment(ev.end);
				var key = startMoment.format('YYYY-MM-DD');

				days[key].left = (startMoment.hour() + (startMoment.minute() / 60) - 9) / 9 * 100;
				days[key].right = -((endMoment.hour() + (endMoment.minute() / 60) - 18) / 9 * 100);

				days[key].start = startMoment;
				days[key].end = endMoment;
			}
		}

		res.render('index', { days: days });
	});

});

var server = app.listen(5000, function () {

  var host = server.address().address;
  var port = server.address().port;

  console.log('App listening at http://%s:%s', host, port);

});
<commit_msg>fixed some things<commit_after>var express = require('express');
var app = express();
var swig = require('swig');
var ical = require('ical');
var moment = require('moment');

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

var url = 'https://www.google.com/calendar/ical/5lbbqnn4nejdarbi983749jv10%40group.calendar.google.com/public/basic.ics';

app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/templates');
app.set('view cache', false);
swig.setDefaults({ cache: false });

app.use(express.static(__dirname + '/public'));

app.get('/', function (req, res) {

	var days = {};
	var next = moment();
	var end = next.clone().add(1, 'months');
	while (next <= end) {
		var currentDate = next.clone();
		days[currentDate.format('YYYY-MM-DD')] = {
			moment: currentDate
		};
		next.add(1, 'days');
	}

	ical.fromURL(url, {}, function(err, data) {
		for (var k in data) {
			if (data.hasOwnProperty(k)) {
				var ev = data[k];
				var startMoment = moment(ev.start);
				var endMoment = moment(ev.end);
				var key = startMoment.format('YYYY-MM-DD');

				days[key].left = (startMoment.hour() + (startMoment.minute() / 60) - 9) / 9 * 100;
				days[key].right = -((endMoment.hour() + (endMoment.minute() / 60) - 18) / 9 * 100);

				days[key].start = startMoment;
				days[key].end = endMoment;
			}
		}

		res.render('index', { days: days });
	});

});

var server = app.listen(63203, function () {

  var host = server.address().address;
  var port = server.address().port;

  console.log('App listening at http://%s:%s', host, port);

});
<|endoftext|>


<commit_before>var fs = require('fs'),
    split = require('split'),
    through = require('through');

module.exports = fileStream;

function fileStream(options) {

  options = options || {};

  var tr = through(write, noop),
      file = null,
      files = [];

  return tr;

  function processFile(filename) {
    var line = 1,
        file = fs.createReadStream(filename).pipe(split());

    file.on('data', onData);
    file.on('end', onEnd);
    file.on('error', noop);

    function onData(data) {

      if (!data) return ++line;

      var fileObject = {
        filename: filename,
        line: line,
        data: data
      };

      tr.queue(fileObject);

      line++;

    }

    function onEnd() {
      if (files.length) processFile(files.shift());
    }

 }

  function write(buf) {
    files.push(buf.toString());
    if (file != null) return;
    file = true;
    processFile(files.shift());
  }

  function noop() {}
}

<commit_msg>fix up a bit<commit_after>var fs = require('fs'),
    split = require('split'),
    through = require('through')

module.exports = fileStream

function fileStream(options) {

  options = options || {}

  var tr = through(write, noop),
      file = null,
      files = []

  return tr

  function processFile(filename) {
    var line = 1,
        file = fs.createReadStream(filename).pipe(split())

    file.on('data', onData)
    file.on('end', onEnd)
    file.on('error', noop)

    function onData(data) {

      if (!data) return ++line

      var fileObject = {
        filename: filename,
        line: line,
        data: data
      }

      tr.queue(fileObject)

      line++

    }

    function onEnd() {
      if (files.length) processFile(files.shift())
    }
 }

  function write(buf) {
    files.push(buf.toString())
    if (file != null) return
    file = true
    processFile(files.shift())
  }

  function noop() {}
}
<|endoftext|>


<commit_before>module.exports = function () {
  this.filter("stylus", (source, options) => {
    try {
      return require("stylus")(source, options).render()
    } catch (e) { throw e }
  })
}
<commit_msg>declare output extension<commit_after>module.exports = function () {
  this.filter("stylus", (source, options) => {
    try {
      return require("stylus")(source, options).render()
    } catch (e) { throw e }
  }, { ext: ".css" })
}
<|endoftext|>


<commit_before>/*!
* vdom-virtualize
* Copyright 2014 by Marcel Klehr <mklehr@gmx.net>
*
* (MIT LICENSE)
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
var VNode = require("virtual-dom/vnode/vnode")
  , VText = require("virtual-dom/vnode/vtext")

module.exports = createVNode

function createVNode(domNode, key) {
  key = key || null // XXX: Leave out `key` for now... merely used for (re-)ordering

  if(domNode.nodeType == 1) return createFromElement(domNode, key)
  if(domNode.nodeType == 3) return createFromTextNode(domNode, key)
  return
}

createVNode.fromHTML = function(html, key) {
  var domNode = document.createElement('div'); // create container
  domNode.innerHTML = html; // browser parses HTML into DOM tree
  return createVNode(domNode.children[0], key);
};

function createFromTextNode(tNode) {
  return new VText(tNode.nodeValue)
}

function createFromElement(el) {
  var tagName = el.tagName
  , namespace = el.namespaceURI == 'http://www.w3.org/1999/xhtml'? null : el.namespaceURI
  , properties = getElementProperties(el)
  , children = []

  for (var i = 0; i < el.childNodes.length; i++) {
    children.push(createVNode(el.childNodes[i]/*, i*/))
  }

  return new VNode(tagName, properties, children, null, namespace)
}

function getElementProperties(el) {
  var obj = {}

  props.forEach(function(propName) {
    if(!el[propName]) return

    if(el[propName] instanceof Element) return

    // Special case: style
    // .style is a DOMStyleDeclaration, thus we need to iterate over all
    // rules to create a hash of applied css properties.
    //
    // You can directly set a specific .style[prop] = value so patching with vdom
    // is possible.
    if("style" == propName) {
      var css = {}
        , styleProp
      if (el.style.length) {
        for(var i=0; i<el.style.length; i++) {
          styleProp = el.style[i]
          css[styleProp] = el.style.getPropertyValue(styleProp) // XXX: add support for "!important" via getPropertyPriority()!
        }
      } else { // IE8
        for (var styleProp in el.style) {
          if (el.style[styleProp]) {
            css[styleProp] = el.style[styleProp];
          }
        }
      }

      obj[propName] = css
      return
    }

    // https://msdn.microsoft.com/en-us/library/cc848861%28v=vs.85%29.aspx
    // The img element does not support the HREF content attribute.
    // In addition, the href property is read-only for the img Document Object Model (DOM) object
    if (el.tagName.toLowerCase() === 'img' && propName === 'href') {
      return;
    }

    // Special case: dataset
    // we can iterate over .dataset with a simple for..in loop.
    // The all-time foo with data-* attribs is the dash-snake to camelCase
    // conversion.
    //
    // *This is compatible with h(), but not with every browser, thus this section was removed in favor
    // of attributes (specified below)!*
    //
    // .dataset properties are directly accessible as transparent getters/setters, so
    // patching with vdom is possible.
    /*if("dataset" == propName) {
      var data = {}
      for(var p in el.dataset) {
        data[p] = el.dataset[p]
      }
      obj[propName] = data
      return
    }*/

    // Special case: attributes
    // these are a NamedNodeMap, but we can just convert them to a hash for vdom,
    // because of https://github.com/Matt-Esch/virtual-dom/blob/master/vdom/apply-properties.js#L57
    if("attributes" == propName){
      var atts = Array.prototype.slice.call(el[propName]);
      var hash = atts.reduce(function(o,a){
        var name = a.name;
        if(obj[name]) return o;
        o[name] = el.getAttribute(a.name);
        return o;
      },{});
      return obj[propName] = hash;
    }
    if("tabIndex" == propName && el.tabIndex === -1) return

    // Special case: contentEditable
    // browser use 'inherit' by default on all nodes, but does not allow setting it to ''
    // diffing virtualize dom will trigger error
    // ref: https://github.com/Matt-Esch/virtual-dom/issues/176
    if("contentEditable" == propName && el[propName] === 'inherit') return

    // default: just copy the property
    obj[propName] = el[propName]
    return
  })

  return obj
}

/**
 * DOMNode property white list
 * Taken from https://github.com/Raynos/react/blob/dom-property-config/src/browser/ui/dom/DefaultDOMPropertyConfig.js
 */
var props =

module.exports.properties = [
 "accept"
,"accessKey"
,"action"
,"alt"
,"async"
,"autoComplete"
,"autoPlay"
,"cellPadding"
,"cellSpacing"
,"checked"
,"className"
,"colSpan"
,"content"
,"contentEditable"
,"controls"
,"crossOrigin"
,"data"
//,"dataset" removed since attributes handles data-attributes
,"defer"
,"dir"
,"download"
,"draggable"
,"encType"
,"formNoValidate"
,"href"
,"hrefLang"
,"htmlFor"
,"httpEquiv"
,"icon"
,"id"
,"label"
,"lang"
,"list"
,"loop"
,"max"
,"mediaGroup"
,"method"
,"min"
,"multiple"
,"muted"
,"name"
,"noValidate"
,"pattern"
,"placeholder"
,"poster"
,"preload"
,"radioGroup"
,"readOnly"
,"rel"
,"required"
,"rowSpan"
,"sandbox"
,"scope"
,"scrollLeft"
,"scrolling"
,"scrollTop"
,"selected"
,"span"
,"spellCheck"
,"src"
,"srcDoc"
,"srcSet"
,"start"
,"step"
,"style"
,"tabIndex"
,"target"
,"title"
,"type"
,"value"

// Non-standard Properties
,"autoCapitalize"
,"autoCorrect"
,"property"

, "attributes"
]

var attrs =
module.exports.attrs = [
 "allowFullScreen"
,"allowTransparency"
,"charSet"
,"cols"
,"contextMenu"
,"dateTime"
,"disabled"
,"form"
,"frameBorder"
,"height"
,"hidden"
,"maxLength"
,"role"
,"rows"
,"seamless"
,"size"
,"width"
,"wmode"

// SVG Properties
,"cx"
,"cy"
,"d"
,"dx"
,"dy"
,"fill"
,"fx"
,"fy"
,"gradientTransform"
,"gradientUnits"
,"offset"
,"points"
,"r"
,"rx"
,"ry"
,"spreadMethod"
,"stopColor"
,"stopOpacity"
,"stroke"
,"strokeLinecap"
,"strokeWidth"
,"textAnchor"
,"transform"
,"version"
,"viewBox"
,"x1"
,"x2"
,"x"
,"y1"
,"y2"
,"y"
]
<commit_msg>fromHTML : returning either a Node or a TextNode<commit_after>/*!
* vdom-virtualize
* Copyright 2014 by Marcel Klehr <mklehr@gmx.net>
*
* (MIT LICENSE)
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
var VNode = require("virtual-dom/vnode/vnode")
  , VText = require("virtual-dom/vnode/vtext")

module.exports = createVNode

function createVNode(domNode, key) {
  key = key || null // XXX: Leave out `key` for now... merely used for (re-)ordering

  if(domNode.nodeType == 1) return createFromElement(domNode, key)
  if(domNode.nodeType == 3) return createFromTextNode(domNode, key)
  return
}

createVNode.fromHTML = function(html, key) {
  var domNode = document.createElement('div'); // create container
  domNode.innerHTML = html; // browser parses HTML into DOM tree
  var child = domNode.children.length ? domNode.children[0] : domNode.firstChild;
  return createVNode(child, key);
};

function createFromTextNode(tNode) {
  return new VText(tNode.nodeValue)
}

function createFromElement(el) {
  var tagName = el.tagName
  , namespace = el.namespaceURI == 'http://www.w3.org/1999/xhtml'? null : el.namespaceURI
  , properties = getElementProperties(el)
  , children = []

  for (var i = 0; i < el.childNodes.length; i++) {
    children.push(createVNode(el.childNodes[i]/*, i*/))
  }

  return new VNode(tagName, properties, children, null, namespace)
}

function getElementProperties(el) {
  var obj = {}

  props.forEach(function(propName) {
    if(!el[propName]) return

    if(el[propName] instanceof Element) return

    // Special case: style
    // .style is a DOMStyleDeclaration, thus we need to iterate over all
    // rules to create a hash of applied css properties.
    //
    // You can directly set a specific .style[prop] = value so patching with vdom
    // is possible.
    if("style" == propName) {
      var css = {}
        , styleProp
      if (el.style.length) {
        for(var i=0; i<el.style.length; i++) {
          styleProp = el.style[i]
          css[styleProp] = el.style.getPropertyValue(styleProp) // XXX: add support for "!important" via getPropertyPriority()!
        }
      } else { // IE8
        for (var styleProp in el.style) {
          if (el.style[styleProp]) {
            css[styleProp] = el.style[styleProp];
          }
        }
      }

      obj[propName] = css
      return
    }

    // https://msdn.microsoft.com/en-us/library/cc848861%28v=vs.85%29.aspx
    // The img element does not support the HREF content attribute.
    // In addition, the href property is read-only for the img Document Object Model (DOM) object
    if (el.tagName.toLowerCase() === 'img' && propName === 'href') {
      return;
    }

    // Special case: dataset
    // we can iterate over .dataset with a simple for..in loop.
    // The all-time foo with data-* attribs is the dash-snake to camelCase
    // conversion.
    //
    // *This is compatible with h(), but not with every browser, thus this section was removed in favor
    // of attributes (specified below)!*
    //
    // .dataset properties are directly accessible as transparent getters/setters, so
    // patching with vdom is possible.
    /*if("dataset" == propName) {
      var data = {}
      for(var p in el.dataset) {
        data[p] = el.dataset[p]
      }
      obj[propName] = data
      return
    }*/

    // Special case: attributes
    // these are a NamedNodeMap, but we can just convert them to a hash for vdom,
    // because of https://github.com/Matt-Esch/virtual-dom/blob/master/vdom/apply-properties.js#L57
    if("attributes" == propName){
      var atts = Array.prototype.slice.call(el[propName]);
      var hash = atts.reduce(function(o,a){
        var name = a.name;
        if(obj[name]) return o;
        o[name] = el.getAttribute(a.name);
        return o;
      },{});
      return obj[propName] = hash;
    }
    if("tabIndex" == propName && el.tabIndex === -1) return

    // Special case: contentEditable
    // browser use 'inherit' by default on all nodes, but does not allow setting it to ''
    // diffing virtualize dom will trigger error
    // ref: https://github.com/Matt-Esch/virtual-dom/issues/176
    if("contentEditable" == propName && el[propName] === 'inherit') return

    // default: just copy the property
    obj[propName] = el[propName]
    return
  })

  return obj
}

/**
 * DOMNode property white list
 * Taken from https://github.com/Raynos/react/blob/dom-property-config/src/browser/ui/dom/DefaultDOMPropertyConfig.js
 */
var props =

module.exports.properties = [
 "accept"
,"accessKey"
,"action"
,"alt"
,"async"
,"autoComplete"
,"autoPlay"
,"cellPadding"
,"cellSpacing"
,"checked"
,"className"
,"colSpan"
,"content"
,"contentEditable"
,"controls"
,"crossOrigin"
,"data"
//,"dataset" removed since attributes handles data-attributes
,"defer"
,"dir"
,"download"
,"draggable"
,"encType"
,"formNoValidate"
,"href"
,"hrefLang"
,"htmlFor"
,"httpEquiv"
,"icon"
,"id"
,"label"
,"lang"
,"list"
,"loop"
,"max"
,"mediaGroup"
,"method"
,"min"
,"multiple"
,"muted"
,"name"
,"noValidate"
,"pattern"
,"placeholder"
,"poster"
,"preload"
,"radioGroup"
,"readOnly"
,"rel"
,"required"
,"rowSpan"
,"sandbox"
,"scope"
,"scrollLeft"
,"scrolling"
,"scrollTop"
,"selected"
,"span"
,"spellCheck"
,"src"
,"srcDoc"
,"srcSet"
,"start"
,"step"
,"style"
,"tabIndex"
,"target"
,"title"
,"type"
,"value"

// Non-standard Properties
,"autoCapitalize"
,"autoCorrect"
,"property"

, "attributes"
]

var attrs =
module.exports.attrs = [
 "allowFullScreen"
,"allowTransparency"
,"charSet"
,"cols"
,"contextMenu"
,"dateTime"
,"disabled"
,"form"
,"frameBorder"
,"height"
,"hidden"
,"maxLength"
,"role"
,"rows"
,"seamless"
,"size"
,"width"
,"wmode"

// SVG Properties
,"cx"
,"cy"
,"d"
,"dx"
,"dy"
,"fill"
,"fx"
,"fy"
,"gradientTransform"
,"gradientUnits"
,"offset"
,"points"
,"r"
,"rx"
,"ry"
,"spreadMethod"
,"stopColor"
,"stopOpacity"
,"stroke"
,"strokeLinecap"
,"strokeWidth"
,"textAnchor"
,"transform"
,"version"
,"viewBox"
,"x1"
,"x2"
,"x"
,"y1"
,"y2"
,"y"
]
<|endoftext|>


<commit_before>module.exports = {

  port: 1337,
  serverUrl: process.env.SERVER_URL || 'http://127.0.0.1:1337'

};
<commit_msg>Increase hook timeout to 3 min<commit_after>module.exports = {

  port: 1337,
  serverUrl: process.env.SERVER_URL || 'http://127.0.0.1:1337',

  hookTimeout: 180000

};
<|endoftext|>


<commit_before>/**
 * RabbitMQ job subscribe & publish functions for Runnable
 * @module ./index
 */
'use strict';

require('loadenv')();

var EventEmitter = require('events').EventEmitter;
var amqplib = require('amqplib/callback_api');
var async = require('async');
var debug = require('debug')('hermes:index');
var hasKeypaths = require('101/has-keypaths');
var isFunction = require('101/is-function');
var util = require('util');
var uuid = require('node-uuid');

// Temporarily hard coded
var queues = [
  'container-create'
];
var hermes;

/**
 * Hermes - Runnable job queue API
 * @class
 * @throws
 * @param {Object} opts
 * @return this
 */
function Hermes (opts) {
  var requiredOpts = ['hostname', 'port', 'username', 'password'];
  if (!hasKeypaths(opts, requiredOpts)) {
    throw new Error('Hermes missing required arguments. Supplied opts '+
                    Object.prototype.keys(opts).join(', ')+
                    '. Opts must include: '+
                    requiredOpts.join(', '));
  }
  var _this = this;
  this._channel = null;
  this.publishQueue = [];
  this.subscribeQueue = [];
  this.consumerTags = {};
  var connectionUrl = [
    'amqp://', opts.username, ':', opts.password,
    '@', opts.hostname];
  if (opts.port) {
    // optional port
    connectionUrl.push(':');
    connectionUrl.push(opts.port);
  }
  connectionUrl = connectionUrl.join('');
  debug('connectionUrl', connectionUrl);
  amqplib.connect(connectionUrl, function (err, conn) {
    if (err) { throw err; }
    debug('rabbitmq connected');
    conn.createChannel(function (err, ch) {
      if (err) { throw err; }
      debug('rabbitmq channel created');
      /**
       * Durable queue: https://www.rabbitmq.com/tutorials/tutorial-two-python.html
       * (Message Durability)
       */
      async.forEach(queues, function forEachQueue (queueName, cb) {
        ch.assertQueue(queueName, {durable: true}, cb);
      }, function done (err) {
        if (err) { throw err; }
        _this._channel = ch;
        _this.emit('ready');
      });
    });
  });
  this.on('ready', function () {
    debug('hermes ready');
    var args;
    while(args = _this.publishQueue.pop()) {
      publish.apply(_this, args);
    }
    while(args = _this.subscribeQueue.pop()) {
      subscribe.apply(_this, args);
    }
  });
  this.on('publish', function (queueName, data) {
    debug('hermes publish', queueName, data);
    if (_this._channel) {
      publish(queueName, data);
    }
    else {
      _this.publishQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  this.on('subscribe', function (queueName, cb) {
    debug('hermes subscribe', queueName);
    if (_this._channel) {
      subscribe(queueName, cb);
    }
    else {
      _this.subscribeQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  this.on('unsubscribe', function (queueName, handler, cb) {
    debug('hermes unsubscribe', queueName);
    if (_this._channel) {
      unsubscribe(queueName, handler, cb);
    }
    else {
      _this.subscribeQueue.forEach(function (args) {
        /* args: [queueName, cb] */
        if (handler) {
          if (args[0] === queueName && args[1] === handler) {
            _this.subscribeQueue.splice(_this.subscribeQueue.indexOf(args), 1);
          }
        }
        else if (args[0] === queueName) {
          _this.subscribeQueue.splice(_this.subscribeQueue.indexOf(args), 1);
        }
      });
      cb();
    }
  });
  /**
   * @param {String} queueName
   * @param {Object} data
   * @return null
   */
  function publish (queueName, data) {
    debug('channel.sendToQueue', queueName, data);
    _this._channel.sendToQueue(queueName, data);
  }
  /**
   * @param {String} queueName
   * @param {Function} cb
   * @return null
   */
  function subscribe (queueName, cb) {
    debug('channel.consume', queueName);
    var consumerTag = [
      uuid.v4(),
      queueName,
      cb.name
    ].join('-');
    _this.consumerTags[consumerTag] = Array.prototype.slice.call(arguments);
    _this._channel.consume(queueName, subscribeCallback(cb), {
      consumerTag: consumerTag
    });
  }
  /**
   * @param {String} queueName
   * @param {Function|null} handler
   * @param {Function} cb
   * @return null
   */
  function unsubscribe (queueName, handler, cb) {
    debug('channel.cancel', queueName);
    var cancelTags = [];
    var tagVal;
    Object.keys(_this.consumerTags).forEach(function (consumerTag) {
      tagVal = _this.consumerTags[consumerTag];
      if (handler) {
        if (tagVal[0] === queueName && tagVal[1] === handler) {
          cancelTags.push(consumerTag);
        }
      }
      else if (tagVal[0] === queueName) {
        cancelTags.push(consumerTag);
      }
    });
    async.eachSeries(cancelTags, _this._channel.cancel, function () {
      cancelTags.forEach(function (cancelTag) {
        delete _this.consumerTags[cancelTag];
      });
      if (isFunction(cb)) {
        cb.apply(_this, arguments);
      }
    });
  }
  /**
   * @param {Function} cb
   * @return Function
   */
  function subscribeCallback (cb) {
    debug('subscribeCallback');
    return function (msg) {
      if (!msg) {
        debug('subscribeCallback invalid message', msg);
        return;
      }
      cb(JSON.parse(msg.content.toString()), function done () {
        debug('subscribeCallback done');
        _this._channel.ack(msg);
      });
    };
  }
  return this;
}

util.inherits(Hermes, EventEmitter);

/**
 * @throws
 * @param {String} queueName
 * @param {Object|String|Buffer} data
 * @return this
 */
Hermes.prototype.publish = function (queueName, data) {
  /*jshint maxcomplexity:7 */
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to publish to invalid queue: '+queueName);
  }
  if (typeof data === 'string' || data instanceof String || data instanceof Buffer) {
    try {
      JSON.parse(data.toString());
    } catch (err) {
      throw new Error('data must be valid JSON');
    }
  }
  else {
    data = new Buffer(JSON.stringify(data));
  }
  this.emit('publish', queueName, data);
  return this;
};

/**
 * @throws
 * @param {String} queueName
 * @param {Function} cb
 * @return this
 */
Hermes.prototype.subscribe = function (queueName, cb) {
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to subscribe to invalid queue: '+queueName);
  }
  if (cb.length !== 2) {
    throw new Error('queue listener callback must take a "done" callback function as a second'+
                    ' argument and invoke the function to send the ACK message to RabbitMQ'+
                    ' and remove the job from the queue.');
  }
  this.emit('subscribe', queueName, cb);
  return this;
};

/**
 * Unsubscribes all workers or individual worker from queue
 * @throws
 * @param {String} queueName
 * @param {Function|null} handler
 * @param {Function} cb (optional)
 * @return this
 */
Hermes.prototype.unsubscribe = function (queueName, handler, cb) {
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to unsubscribe from invalid queue: '+queueName);
  }
  this.emit('unsubscribe', queueName, handler, cb);
  return this;
};

/**
 * Factory method takes configuration once during applicaiton lifecycle and
 * returns instance of hermes
 */
module.exports.hermesSingletonFactory = function (opts) {
  hermes = (hermes) ? hermes : new Hermes(opts);
  return hermes;
};
<commit_msg>hotfix, correctly binding context of cancel when used as a callback method<commit_after>/**
 * RabbitMQ job subscribe & publish functions for Runnable
 * @module ./index
 */
'use strict';

require('loadenv')();

var EventEmitter = require('events').EventEmitter;
var amqplib = require('amqplib/callback_api');
var async = require('async');
var debug = require('debug')('hermes:index');
var hasKeypaths = require('101/has-keypaths');
var isFunction = require('101/is-function');
var util = require('util');
var uuid = require('node-uuid');

// Temporarily hard coded
var queues = [
  'container-create'
];
var hermes;

/**
 * Hermes - Runnable job queue API
 * @class
 * @throws
 * @param {Object} opts
 * @return this
 */
function Hermes (opts) {
  var requiredOpts = ['hostname', 'port', 'username', 'password'];
  if (!hasKeypaths(opts, requiredOpts)) {
    throw new Error('Hermes missing required arguments. Supplied opts '+
                    Object.prototype.keys(opts).join(', ')+
                    '. Opts must include: '+
                    requiredOpts.join(', '));
  }
  var _this = this;
  this._channel = null;
  this.publishQueue = [];
  this.subscribeQueue = [];
  this.consumerTags = {};
  var connectionUrl = [
    'amqp://', opts.username, ':', opts.password,
    '@', opts.hostname];
  if (opts.port) {
    // optional port
    connectionUrl.push(':');
    connectionUrl.push(opts.port);
  }
  connectionUrl = connectionUrl.join('');
  debug('connectionUrl', connectionUrl);
  amqplib.connect(connectionUrl, function (err, conn) {
    if (err) { throw err; }
    debug('rabbitmq connected');
    conn.createChannel(function (err, ch) {
      if (err) { throw err; }
      debug('rabbitmq channel created');
      /**
       * Durable queue: https://www.rabbitmq.com/tutorials/tutorial-two-python.html
       * (Message Durability)
       */
      async.forEach(queues, function forEachQueue (queueName, cb) {
        ch.assertQueue(queueName, {durable: true}, cb);
      }, function done (err) {
        if (err) { throw err; }
        _this._channel = ch;
        _this.emit('ready');
      });
    });
  });
  this.on('ready', function () {
    debug('hermes ready');
    var args;
    while(args = _this.publishQueue.pop()) {
      publish.apply(_this, args);
    }
    while(args = _this.subscribeQueue.pop()) {
      subscribe.apply(_this, args);
    }
  });
  this.on('publish', function (queueName, data) {
    debug('hermes publish', queueName, data);
    if (_this._channel) {
      publish(queueName, data);
    }
    else {
      _this.publishQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  this.on('subscribe', function (queueName, cb) {
    debug('hermes subscribe', queueName);
    if (_this._channel) {
      subscribe(queueName, cb);
    }
    else {
      _this.subscribeQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  this.on('unsubscribe', function (queueName, handler, cb) {
    debug('hermes unsubscribe', queueName);
    if (_this._channel) {
      unsubscribe(queueName, handler, cb);
    }
    else {
      _this.subscribeQueue.forEach(function (args) {
        /* args: [queueName, cb] */
        if (handler) {
          if (args[0] === queueName && args[1] === handler) {
            _this.subscribeQueue.splice(_this.subscribeQueue.indexOf(args), 1);
          }
        }
        else if (args[0] === queueName) {
          _this.subscribeQueue.splice(_this.subscribeQueue.indexOf(args), 1);
        }
      });
      cb();
    }
  });
  /**
   * @param {String} queueName
   * @param {Object} data
   * @return null
   */
  function publish (queueName, data) {
    debug('channel.sendToQueue', queueName, data);
    _this._channel.sendToQueue(queueName, data);
  }
  /**
   * @param {String} queueName
   * @param {Function} cb
   * @return null
   */
  function subscribe (queueName, cb) {
    debug('channel.consume', queueName);
    var consumerTag = [
      uuid.v4(),
      queueName,
      cb.name
    ].join('-');
    _this.consumerTags[consumerTag] = Array.prototype.slice.call(arguments);
    _this._channel.consume(queueName, subscribeCallback(cb), {
      consumerTag: consumerTag
    });
  }
  /**
   * @param {String} queueName
   * @param {Function|null} handler
   * @param {Function} cb
   * @return null
   */
  function unsubscribe (queueName, handler, cb) {
    debug('channel.cancel', queueName);
    var cancelTags = [];
    var tagVal;
    Object.keys(_this.consumerTags).forEach(function (consumerTag) {
      tagVal = _this.consumerTags[consumerTag];
      if (handler) {
        if (tagVal[0] === queueName && tagVal[1] === handler) {
          cancelTags.push(consumerTag);
        }
      }
      else if (tagVal[0] === queueName) {
        cancelTags.push(consumerTag);
      }
    });
    async.eachSeries(cancelTags, _this._channel.cancel.bind(_this._channel), function () {
      cancelTags.forEach(function (cancelTag) {
        delete _this.consumerTags[cancelTag];
      });
      if (isFunction(cb)) {
        cb.apply(_this, arguments);
      }
    });
  }
  /**
   * @param {Function} cb
   * @return Function
   */
  function subscribeCallback (cb) {
    debug('subscribeCallback');
    return function (msg) {
      if (!msg) {
        debug('subscribeCallback invalid message', msg);
        return;
      }
      cb(JSON.parse(msg.content.toString()), function done () {
        debug('subscribeCallback done');
        _this._channel.ack(msg);
      });
    };
  }
  return this;
}

util.inherits(Hermes, EventEmitter);

/**
 * @throws
 * @param {String} queueName
 * @param {Object|String|Buffer} data
 * @return this
 */
Hermes.prototype.publish = function (queueName, data) {
  /*jshint maxcomplexity:7 */
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to publish to invalid queue: '+queueName);
  }
  if (typeof data === 'string' || data instanceof String || data instanceof Buffer) {
    try {
      JSON.parse(data.toString());
    } catch (err) {
      throw new Error('data must be valid JSON');
    }
  }
  else {
    data = new Buffer(JSON.stringify(data));
  }
  this.emit('publish', queueName, data);
  return this;
};

/**
 * @throws
 * @param {String} queueName
 * @param {Function} cb
 * @return this
 */
Hermes.prototype.subscribe = function (queueName, cb) {
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to subscribe to invalid queue: '+queueName);
  }
  if (cb.length !== 2) {
    throw new Error('queue listener callback must take a "done" callback function as a second'+
                    ' argument and invoke the function to send the ACK message to RabbitMQ'+
                    ' and remove the job from the queue.');
  }
  this.emit('subscribe', queueName, cb);
  return this;
};

/**
 * Unsubscribes all workers or individual worker from queue
 * @throws
 * @param {String} queueName
 * @param {Function|null} handler
 * @param {Function} cb (optional)
 * @return this
 */
Hermes.prototype.unsubscribe = function (queueName, handler, cb) {
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to unsubscribe from invalid queue: '+queueName);
  }
  this.emit('unsubscribe', queueName, handler, cb);
  return this;
};

/**
 * Factory method takes configuration once during applicaiton lifecycle and
 * returns instance of hermes
 */
module.exports.hermesSingletonFactory = function (opts) {
  hermes = (hermes) ? hermes : new Hermes(opts);
  return hermes;
};
<|endoftext|>