<commit_before>/**
 * gulp-boilerplate
 * @param Gulp gulp
 */
module.exports = (function(gulp) {

    // Include our dependencies, starting with style stuff
    var sass        = require('gulp-sass'),
        autoprefix  = require('gulp-autoprefixer'),
        minify      = require('gulp-minify-css'),
        rename      = require('gulp-rename'),

        // Scripts
        uglify      = require('gulp-uglify'),
        strip       = require('gulp-strip-debug'),
        concat      = require('gulp-concat'),

        // Images
        cache       = require('gulp-cache'),

        // Other
        util        = require('gulp-util'),
        del         = require('del'),
        bust        = require('gulp-buster'),
        notify      = require('gulp-notify'),
        notifier    = require('node-notifier'),
        merge       = require('merge-stream')
        sequence    = require('run-sequence');

    // Store default globalSettings for all tasks
    var globalSettings = {

        // Deploy task globalSettings
        deploy: {
            files: ['**/*'],
            destination: '_deploy'
        },

        // Style task globalSettings
        styles: {
            autoprefix: {
                browsers: "last 15 versions"
            },
            public: 'public/styles',
            src: 'assets/styles/**/*.scss',
            cache: 'public/cache',
            sass: {
                sourceComments: 'normal'
            },
            minify: false
        },

        // Script task globalSettings
        scripts: {
            src: 'assets/js/**/*.js',
            filename: 'main.min.js',
            public: 'public/js',
            cache: 'public/cache',
            uglify: false,
            strip: false
        },

        // Images task globalSettings
        images: {
            src: 'assets/img/**/*',
            public: 'public/img'
        },

        // Clean task globalSettings
        clean: {
            paths: [
                'public/styles',
                'public/js',
                'public/img'
            ],
        },

        // Default task globalSettings
        standard: {
            notify: {message: 'Tasks complete'},
            watch: true,
            clean: true,
            tasks: ['scripts', 'styles', 'images']
        },

        // Watch task globalSettings
        watch: {
            tasks: [
                {path: 'assets/styles/**/*.scss', tasks: ['styles']},
                {path: 'assets/js/**/*.js', tasks: ['scripts']},
                {path: 'assets/img/**/*', tasks: ['images']}
            ]
        },
    };

    /**
     * Handle errors
     *
     * @param error
     */
    var _logErrors = function(error)
    {
        console.log("An error has occured:");
        console.log(error.toString());

        util.log(error);
        this.emit('end');
    };

    /**
     * Handle option setting
     *
     * @param Object defaults  Default options
     * @param Object supplied User supplied
     */
    function _setOptions(defaults, supplied)
    {
        if(supplied === undefined) return defaults;

        var options = defaults;

        for(key in supplied) {
            var option = supplied[key];

            if(option !== undefined) {
                options[key] = supplied[key];
            } else if(typeof option === 'object') {
                options[key] = _setOptions(defaults[key], supplied[key]);
            }
        }

        return options;
    };

    /**
     * Deployment task
     *
     * @param  Object customOptions
     * @return Function
     */
    function deploy(customOptions)
    {
        var options = _setOptions(globalSettings.deploy, customOptions);

        return function() {
            return gulp.src(options.files, {base: '.'}).pipe(gulp.dest(options.destination));
        };
    };

    /**
     * Styles task
     *
     * @param  Object customOptions
     * @return Function
     */
    function styles(customOptions)
    {
        var options = _setOptions(globalSettings.styles, customOptions);

        return function() {
            var styles = gulp.src(options.src)
                .pipe(sass(options.sass))
                .on('error', _logErrors)
                .on('error', notify.onError('Error: <%= error.message %>'))
                .pipe(autoprefix(options.autoprefix));

            if(options.minify === true) {
                styles = styles.pipe(minify());
            }

            return styles.pipe(gulp.dest(options.public))
                .pipe(bust())
                .pipe(gulp.dest(options.cache));
        };
    };

    /**
     * Scripts task
     *
     * @param  Object customOptions
     * @return Function
     */
    function scripts(customOptions)
    {
        var options = _setOptions(globalSettings.scripts, customOptions);

        return function() {
            var scripts = gulp.src(options.src).pipe(concat(options.filename));

            if(options.strip == true) {
                scripts = scripts.pipe(strip());
            }

            if(options.uglify == true) {
                scripts = scripts.pipe(uglify());
            }

            return scripts.pipe(gulp.dest(options.public))
                .pipe(bust())
                .pipe(gulp.dest(options.cache));
        };
    };

    /**
     * Images task
     *
     * @param  Object customOptions
     * @return Function
     */
    function images(customOptions)
    {
        var options = _setOptions(globalSettings.images, customOptions);

        return function() {
            return gulp.src(options.src)
                .pipe(gulp.dest(options.public));
        };
    };

    /**
     * Clear task
     *
     * @return Function
     */
    function clear()
    {
        return function(done) {
            return cache.clearAll(done);
        };
    };

    /**
     * Clean task
     *
     * @param  Object customOptions
     * @return Function
     */
    function clean(customOptions)
    {
        var options = _setOptions(globalSettings.clean, customOptions);

        return function(cb) {
            return del(options.paths, cb);
        };
    };

    /**
     * Production task
     *
     * @param  Object customOptions
     * @return Function
     */
    function production(customOptions)
    {
        var options = globalSettings;
        var correct = customOptions.hasOwnProperty('styles') && customOptions.hasOwnProperty('scripts') && customOptions.hasOwnProperty('images');

        if(customOptions != 'undefined' && correct) {
            options = {
                styles: _setOptions(globalSettings.styles, customOptions.styles),
                scripts: _setOptions(globalSettings.scripts, customOptions.scripts),
                images: _setOptions(globalSettings.images, customOptions.images)
            };
        }

        return function() {
            var stylesOptions = _setOptions(options.styles, {minify: true});
            var scriptsOptions = _setOptions(options.scripts, {strip: true, uglify: true});

            // Return the streams in one combined stream
            return merge(styles(stylesOptions)(), scripts(scriptsOptions)(), images(options.images)());
        };
    };

    /**
     * Standard task
     *
     * @param  Object customOptions
     * @return Function
     */
    function standard(customOptions)
    {
        var options = _setOptions(globalSettings.standard, customOptions);

        return function(callback) {

            if(options.clean === true && options.watch === true) {
                sequence('clean', options.tasks, 'watch', callback);
            } else if(options.clean === true && options.watch === false) {
                sequence('clean', options.tasks, callback);
            } else if(options.clean === false && options.watch === true) {
                sequence(options.tasks, 'watch', callback);
            } else {
                sequence(options.tasks, callback);
            }

            notifier.notify(options.notify);
        };
    };

    /**
     * Watch task
     *
     * @param  Object customOptions
     * @return Function
     */
    function watch(customOptions)
    {
        var options = _setOptions(globalSettings.watch, customOptions);

        return function() {
            for(index in options.tasks) {
                var task = options.tasks[index];
                gulp.watch(task.path, task.tasks);
            }
        };
    };

    // Give access to the tasks
    return {
        styles: styles,
        scripts: scripts,
        images: images,
        clear: clear,
        clean: clean,
        production: production,
        deploy: deploy,
        standard: standard,
        watch: watch
    };

});
<commit_msg>:bug: Oops I'm so silly<commit_after>/**
 * gulp-boilerplate
 * @param Gulp gulp
 */
module.exports = (function(gulp) {

    // Include our dependencies, starting with style stuff
    var sass        = require('gulp-sass'),
        autoprefix  = require('gulp-autoprefixer'),
        minify      = require('gulp-minify-css'),
        rename      = require('gulp-rename'),

        // Scripts
        uglify      = require('gulp-uglify'),
        strip       = require('gulp-strip-debug'),
        concat      = require('gulp-concat'),

        // Images
        cache       = require('gulp-cache'),

        // Other
        util        = require('gulp-util'),
        del         = require('del'),
        bust        = require('gulp-buster'),
        notify      = require('gulp-notify'),
        notifier    = require('node-notifier'),
        merge       = require('merge-stream')
        sequence    = require('run-sequence');

    // Store default globalSettings for all tasks
    var globalSettings = {

        // Deploy task globalSettings
        deploy: {
            files: ['**/*'],
            destination: '_deploy'
        },

        // Style task globalSettings
        styles: {
            autoprefix: {
                browsers: "last 15 versions"
            },
            public: 'public/styles',
            src: 'assets/styles/**/*.scss',
            cache: 'public/cache',
            sass: {
                sourceComments: 'normal'
            },
            minify: false
        },

        // Script task globalSettings
        scripts: {
            src: 'assets/js/**/*.js',
            filename: 'main.min.js',
            public: 'public/js',
            cache: 'public/cache',
            uglify: false,
            strip: false
        },

        // Images task globalSettings
        images: {
            src: 'assets/img/**/*',
            public: 'public/img'
        },

        // Clean task globalSettings
        clean: {
            paths: [
                'public/styles',
                'public/js',
                'public/img'
            ],
        },

        // Default task globalSettings
        standard: {
            notify: {message: 'Tasks complete'},
            watch: true,
            clean: true,
            tasks: ['scripts', 'styles', 'images']
        },

        // Watch task globalSettings
        watch: {
            tasks: [
                {path: 'assets/styles/**/*.scss', tasks: ['styles']},
                {path: 'assets/js/**/*.js', tasks: ['scripts']},
                {path: 'assets/img/**/*', tasks: ['images']}
            ]
        },
    };

    /**
     * Handle errors
     *
     * @param error
     */
    var _logErrors = function(error)
    {
        console.log("An error has occured:");
        console.log(error.toString());

        util.log(error);
        this.emit('end');
    };

    /**
     * Handle option setting
     *
     * @param Object defaults  Default options
     * @param Object supplied User supplied
     */
    function _setOptions(defaults, supplied)
    {
        if(supplied === undefined) return defaults;

        var options = defaults;

        for(key in supplied) {
            var option = supplied[key];

            if(option !== undefined) {
                options[key] = supplied[key];
            } else if(typeof option === 'object') {
                options[key] = _setOptions(defaults[key], supplied[key]);
            }
        }

        return options;
    };

    /**
     * Deployment task
     *
     * @param  Object customOptions
     * @return Function
     */
    function deploy(customOptions)
    {
        var options = _setOptions(globalSettings.deploy, customOptions);

        return function() {
            return gulp.src(options.files, {base: '.'}).pipe(gulp.dest(options.destination));
        };
    };

    /**
     * Styles task
     *
     * @param  Object customOptions
     * @return Function
     */
    function styles(customOptions)
    {
        var options = _setOptions(globalSettings.styles, customOptions);

        return function() {
            var styles = gulp.src(options.src)
                .pipe(sass(options.sass))
                .on('error', _logErrors)
                .on('error', notify.onError('Error: <%= error.message %>'))
                .pipe(autoprefix(options.autoprefix));

            if(options.minify === true) {
                styles = styles.pipe(minify());
            }

            return styles.pipe(gulp.dest(options.public))
                .pipe(bust())
                .pipe(gulp.dest(options.cache));
        };
    };

    /**
     * Scripts task
     *
     * @param  Object customOptions
     * @return Function
     */
    function scripts(customOptions)
    {
        var options = _setOptions(globalSettings.scripts, customOptions);

        return function() {
            var scripts = gulp.src(options.src).pipe(concat(options.filename));

            if(options.strip == true) {
                scripts = scripts.pipe(strip());
            }

            if(options.uglify == true) {
                scripts = scripts.pipe(uglify());
            }

            return scripts.pipe(gulp.dest(options.public))
                .pipe(bust())
                .pipe(gulp.dest(options.cache));
        };
    };

    /**
     * Images task
     *
     * @param  Object customOptions
     * @return Function
     */
    function images(customOptions)
    {
        var options = _setOptions(globalSettings.images, customOptions);

        return function() {
            return gulp.src(options.src)
                .pipe(gulp.dest(options.public));
        };
    };

    /**
     * Clear task
     *
     * @return Function
     */
    function clear()
    {
        return function(done) {
            return cache.clearAll(done);
        };
    };

    /**
     * Clean task
     *
     * @param  Object customOptions
     * @return Function
     */
    function clean(customOptions)
    {
        var options = _setOptions(globalSettings.clean, customOptions);

        return function(cb) {
            return del(options.paths, cb);
        };
    };

    /**
     * Production task
     *
     * @param  Object customOptions
     * @return Function
     */
    function production(customOptions)
    {
        var options = globalSettings;

        if(customOptions != 'undefined') {
            var correct = customOptions.hasOwnProperty('styles') && customOptions.hasOwnProperty('scripts') && customOptions.hasOwnProperty('images');
            if(correct) {
                options = {
                    styles: _setOptions(globalSettings.styles, customOptions.styles),
                    scripts: _setOptions(globalSettings.scripts, customOptions.scripts),
                    images: _setOptions(globalSettings.images, customOptions.images)
                };
            }
        }

        return function() {
            var stylesOptions = _setOptions(options.styles, {minify: true});
            var scriptsOptions = _setOptions(options.scripts, {strip: true, uglify: true});

            // Return the streams in one combined stream
            return merge(styles(stylesOptions)(), scripts(scriptsOptions)(), images(options.images)());
        };
    };

    /**
     * Standard task
     *
     * @param  Object customOptions
     * @return Function
     */
    function standard(customOptions)
    {
        var options = _setOptions(globalSettings.standard, customOptions);

        return function(callback) {

            if(options.clean === true && options.watch === true) {
                sequence('clean', options.tasks, 'watch', callback);
            } else if(options.clean === true && options.watch === false) {
                sequence('clean', options.tasks, callback);
            } else if(options.clean === false && options.watch === true) {
                sequence(options.tasks, 'watch', callback);
            } else {
                sequence(options.tasks, callback);
            }

            notifier.notify(options.notify);
        };
    };

    /**
     * Watch task
     *
     * @param  Object customOptions
     * @return Function
     */
    function watch(customOptions)
    {
        var options = _setOptions(globalSettings.watch, customOptions);

        return function() {
            for(index in options.tasks) {
                var task = options.tasks[index];
                gulp.watch(task.path, task.tasks);
            }
        };
    };

    // Give access to the tasks
    return {
        styles: styles,
        scripts: scripts,
        images: images,
        clear: clear,
        clean: clean,
        production: production,
        deploy: deploy,
        standard: standard,
        watch: watch
    };

});
<|endoftext|>


<commit_before>/* eslint-env node */
'use strict';
const fastbootTransform = require('fastboot-transform');

module.exports = {
  name: 'ember-fullcalendar',

  // isDevelopingAddon: function() {
  //   return true;
  // },

  options: {
    nodeAssets: {
      'fullcalendar': {
        function() {
          return {
            import: {
              include: ['dist/fullcalendar.js', 'dist/fullcalendar.css'].concat(this.includeLocalesFiles),
              processTree(input) {
                return fastbootTransform(input);
              }
            }
          }
        }
      },
      'fullcalendar-scheduler': {
        enabled: this.includeScheduler,
        import: {
          include: ['dist/scheduler.js', 'dist/scheduler.css'],
          processTree(input) {
            return fastbootTransform(input);
          }
        }
      }
    }
  },

  included(app, parentAddon) {
    var target = parentAddon || app;

    // allow addon to be nested - see: https://github.com/ember-cli/ember-cli/issues/3718
    if (target.app) {
      target = target.app;
    }

    var config = target.project.config(target.env) || {};

    // include locale files
    if (config.emberFullCalendar && config.emberFullCalendar.includeLocales) {
      if (Array.isArray(config.emberFullCalendar.includeLocales)) {
        this.includeLocalesFiles = config.emberFullCalendar.includeLocales.map(function(localeCode) {
          return 'dist/locale/' + localeCode + '.js';
        });
      } else if (config.emberFullCalendar.includeLocales === "all") {
        this.includeLocalesFiles = ['dist/locale-all.js'];
      } else {
        this.includeLocalesFiles = [];
      }
    } else {
      this.includeLocalesFiles = [];
    }

    // Add scheduler to executable unless configured not to.
    if (config.emberFullCalendar && config.emberFullCalendar.includeScheduler === true) {
      this.includeScheduler = true;
    } else {
      this.includeScheduler = false;
    }

    this._super.included.apply(this, arguments);
  }
};
<commit_msg>Remove extra hash<commit_after>/* eslint-env node */
'use strict';
const fastbootTransform = require('fastboot-transform');

module.exports = {
  name: 'ember-fullcalendar',

  // isDevelopingAddon: function() {
  //   return true;
  // },

  options: {
    nodeAssets: {
      'fullcalendar': function() {
        return {
          import: {
            include: ['dist/fullcalendar.js', 'dist/fullcalendar.css'].concat(this.includeLocalesFiles),
            processTree(input) {
              return fastbootTransform(input);
            }
          }
        }
      },
      'fullcalendar-scheduler': {
        enabled: this.includeScheduler,
        import: {
          include: ['dist/scheduler.js', 'dist/scheduler.css'],
          processTree(input) {
            return fastbootTransform(input);
          }
        }
      }
    }
  },

  included(app, parentAddon) {
    var target = parentAddon || app;

    // allow addon to be nested - see: https://github.com/ember-cli/ember-cli/issues/3718
    if (target.app) {
      target = target.app;
    }

    var config = target.project.config(target.env) || {};

    // include locale files
    if (config.emberFullCalendar && config.emberFullCalendar.includeLocales) {
      if (Array.isArray(config.emberFullCalendar.includeLocales)) {
        this.includeLocalesFiles = config.emberFullCalendar.includeLocales.map(function(localeCode) {
          return 'dist/locale/' + localeCode + '.js';
        });
      } else if (config.emberFullCalendar.includeLocales === "all") {
        this.includeLocalesFiles = ['dist/locale-all.js'];
      } else {
        this.includeLocalesFiles = [];
      }
    } else {
      this.includeLocalesFiles = [];
    }

    // Add scheduler to executable unless configured not to.
    if (config.emberFullCalendar && config.emberFullCalendar.includeScheduler === true) {
      this.includeScheduler = true;
    } else {
      this.includeScheduler = false;
    }

    this._super.included.apply(this, arguments);
  }
};
<|endoftext|>


<commit_before>'use strict';
const {globalShortcut, ipcMain, dialog} = require('electron');
const menubar = require('menubar');
const Stopwatch = require('timer-stopwatch');
const Hrt = require('human-readable-time');
const fs = require('fs');

const path = require('path');
const AutoLaunch = require('auto-launch');

let timeFormat = new Hrt('%mm%:%ss%');
let workTimer = 1500000;
let relaxTimer = 300000;
let longRelaxTimer = 900000;
let pomodoroCount = 0;
let isRelaxTime = false;
let showTimer = true;
let launchOnStartup = false;
let icon = (process.platform === 'darwin') ? '/build/IconTemplate.png' : '/build/winIcon.png'

let mb = menubar({
	dir: path.join(__dirname, '/src'),
	preloadWindow: true,
	tooltip: 'Pomodoro timer',
	height: 330,
	width: 340,
	icon: path.join(__dirname, icon)
});
let options = {
	name: 'Pomodoro',
	path: (process.platform === 'darwin') ?
		path.join(mb.app.getAppPath(), 'Pomodoro.app') :
		path.join(mb.app.getAppPath(), 'Pomodoro.exe')
};

let autolauncher = new AutoLaunch(options);

getConfig();

global.timer = new Stopwatch(workTimer);
global.isRelaxTime = isRelaxTime;

process.on('uncaughtException', (err) => {
	console.log(err.stack);
	dialog.showErrorBox('Uncaught Exception: ' + err.message, err.stack || '');
	mb.app.quit();
});

mb.app.on('will-quit', () => {
	globalShortcut.unregisterAll();
	global.timer.stop();
});

mb.app.on('quit', () => {
	mb = null;
});

global.timer.on('time', function(time) {
	if(showTimer) {
    if (time.ms !== workTimer
	       || time.ms !== relaxTimer
	       || time.ms !== longRelaxTimer) {
		  mb.tray.setTitle(timeFormat(new Date(time.ms)));
    }
	} else {
    mb.tray.setTitle('');
  }

	mb.window.webContents.send('update-timer', getProgress());
});

global.timer.on('done', function() {
	mb.window.webContents.send('end-timer');

	if(isRelaxTime) {
		isRelaxTime = false;
		global.timer.reset(workTimer);
	} else {
		isRelaxTime = true;
		pomodoroCount++;
		if(pomodoroCount % 4 === 0) {
			global.timer.reset(longRelaxTimer);
		} else {
			global.timer.reset(relaxTimer);
		}
	}

	global.isRelaxTime = isRelaxTime;
	global.pomodoroCount = pomodoroCount;
});

ipcMain.on('reset-timer', function(event) {
	global.timer.reset(workTimer);
	mb.tray.setTitle('');
	global.progress = getProgress();
	mb.window.webContents.send('update-timer', 0);
});

ipcMain.on('toggle-timer', function() {
	global.timer.startstop();
	mb.window.webContents.send('update-timer', getProgress());
	if(global.timer.runTimer === false) mb.tray.setTitle('Paused');
});

ipcMain.on('settings-updated', function(event) {
	getConfig();

	mb.window.webContents.send('update-timer', getProgress());
});

ipcMain.on('request-config', function(event) {
	getConfig();

	event.returnValue = {
		workTimer: workTimer / 60 / 1000,
		relaxTimer: relaxTimer / 60 / 1000,
		longRelaxTimer: longRelaxTimer / 60 / 1000,
    showTimer: showTimer,
		launchOnStartup: launchOnStartup
	};
});

ipcMain.on('quit', function() {
	mb.app.quit();
});

function getConfig() {
	try {
		let dataPath = path.join(mb.app.getPath('userData'), 'config.json');
		let data = JSON.parse(fs.readFileSync(dataPath));

		workTimer = data.workTimer * 60 * 1000;
		relaxTimer = data.relaxTimer * 60 * 1000;
		longRelaxTimer = data.longRelaxTimer * 60 * 1000;
    showTimer = data.showTimer;
		launchOnStartup = data.launchOnStartup;

		launchOnStartup ? autolauncher.enable() : autolauncher.disable();
	} catch(err) {
		console.log(err);
		console.log('Didn\'t find previous config. Using default settings');
	}
}

function getProgress() {
	let progress, max;

	if(isRelaxTime) {
		if(pomodoroCount % 4 === 0) {
			max = longRelaxTimer;
		} else {
			max = relaxTimer;
		}
	} else {
		max = workTimer;
	}

	progress = (max - timer.ms) / (max / 100) * 0.01;

	if(progress < 0) {
		progress = 0.01;
	}
	return progress;
}
<commit_msg>Fix autolaunch<commit_after>'use strict';
const {globalShortcut, ipcMain, dialog} = require('electron');
const menubar = require('menubar');
const Stopwatch = require('timer-stopwatch');
const Hrt = require('human-readable-time');
const fs = require('fs');

const path = require('path');
const AutoLaunch = require('auto-launch');

let timeFormat = new Hrt('%mm%:%ss%');
let workTimer = 1500000;
let relaxTimer = 300000;
let longRelaxTimer = 900000;
let pomodoroCount = 0;
let isRelaxTime = false;
let showTimer = true;
let launchOnStartup = false;
let icon = (process.platform === 'darwin') ? '/src/img/IconTemplate.png' : '/src/img/winIcon.png'

let mb = menubar({
	dir: path.join(__dirname, '/src'),
	preloadWindow: true,
	tooltip: 'Pomodoro timer',
	height: 330,
	width: 340,
	icon: path.join(__dirname, icon)
});

let autolauncher = new AutoLaunch({ name: 'Pomodoro' });

getConfig();

global.timer = new Stopwatch(workTimer);
global.isRelaxTime = isRelaxTime;

process.on('uncaughtException', (err) => {
	console.log(err.stack);
	dialog.showErrorBox('Uncaught Exception: ' + err.message, err.stack || '');
	mb.app.quit();
});

mb.app.on('will-quit', () => {
	globalShortcut.unregisterAll();
	global.timer.stop();
});

mb.app.on('quit', () => {
	mb = null;
});

global.timer.on('time', function(time) {
	if(showTimer) {
    if (time.ms !== workTimer
	       || time.ms !== relaxTimer
	       || time.ms !== longRelaxTimer) {
		  mb.tray.setTitle(timeFormat(new Date(time.ms)));
    }
	} else {
    mb.tray.setTitle('');
  }

	mb.window.webContents.send('update-timer', getProgress());
});

global.timer.on('done', function() {
	mb.window.webContents.send('end-timer');

	if(isRelaxTime) {
		isRelaxTime = false;
		global.timer.reset(workTimer);
	} else {
		isRelaxTime = true;
		pomodoroCount++;
		if(pomodoroCount % 4 === 0) {
			global.timer.reset(longRelaxTimer);
		} else {
			global.timer.reset(relaxTimer);
		}
	}

	global.isRelaxTime = isRelaxTime;
	global.pomodoroCount = pomodoroCount;
});

ipcMain.on('reset-timer', function(event) {
	global.timer.reset(workTimer);
	mb.tray.setTitle('');
	global.progress = getProgress();
	mb.window.webContents.send('update-timer', 0);
});

ipcMain.on('toggle-timer', function() {
	global.timer.startstop();
	mb.window.webContents.send('update-timer', getProgress());
	if(global.timer.runTimer === false) mb.tray.setTitle('Paused');
});

ipcMain.on('settings-updated', function(event) {
	getConfig();

	mb.window.webContents.send('update-timer', getProgress());
});

ipcMain.on('request-config', function(event) {
	getConfig();

	event.returnValue = {
		workTimer: workTimer / 60 / 1000,
		relaxTimer: relaxTimer / 60 / 1000,
		longRelaxTimer: longRelaxTimer / 60 / 1000,
    showTimer: showTimer,
		launchOnStartup: launchOnStartup
	};
});

ipcMain.on('quit', function() {
	mb.app.quit();
});

function getConfig() {
	try {
		let dataPath = path.join(mb.app.getPath('userData'), 'config.json');
		let data = JSON.parse(fs.readFileSync(dataPath));

		workTimer = data.workTimer * 60 * 1000;
		relaxTimer = data.relaxTimer * 60 * 1000;
		longRelaxTimer = data.longRelaxTimer * 60 * 1000;
    showTimer = data.showTimer;
		launchOnStartup = data.launchOnStartup;

		(launchOnStartup ? autolauncher.enable() : autolauncher.disable())
		.then(function(err) {
			dialog.showErrorBox('Error on adding launch on startup functionality', err);
		});
	} catch(err) {
		console.log(err);
		console.log('Didn\'t find previous config. Using default settings');
	}
}

function getProgress() {
	let progress, max;

	if(isRelaxTime) {
		if(pomodoroCount % 4 === 0) {
			max = longRelaxTimer;
		} else {
			max = relaxTimer;
		}
	} else {
		max = workTimer;
	}

	progress = (max - timer.ms) / (max / 100) * 0.01;

	if(progress < 0) {
		progress = 0.01;
	}
	return progress;
}
<|endoftext|>


<commit_before>require('dotenv').config({ path: `${ process.env.PWD }/.env` })

const standardChangelog = require('standard-changelog')
    , conventionalGithubReleaser = require('conventional-github-releaser')
    , bump = require('bump-regex')
    , inquirer = require('inquirer')
    , fs = require('fs')
    , q = require('q')
    , exec = require('child_process').exec
    , concatStream = require('concat-stream')

const PACKAGE_PATH = `${ process.env.PWD }/package.json`
    , CHANGELOG_PATH = `${ process.env.PWD }/CHANGELOG.md`
    , RC_PREID = 'rc'

const VERSION = require(PACKAGE_PATH).version

function get_all_versions() {
    const opts = {
        str: fs.readFileSync(PACKAGE_PATH).toString()
    }
    const sub_opts = {
        str: (function() {
            if (VERSION.match(/-\d+$/)) return opts.str
            return opts.str.replace(
                /(['"]version['"]:\s*['"]).*(['"]),?/,
                `$1${ VERSION + '-0' }$2`
            )
        })()
    }
    return q.all([
        q.nfcall(bump, Object.assign({ type: 'prerelease', preid: RC_PREID }, opts)),
        q.nfcall(bump, Object.assign({ type: 'prerelease' }, sub_opts)),
        q.nfcall(bump, Object.assign({ type: 'patch' }, opts)),
        q.nfcall(bump, Object.assign({ type: 'minor' }, opts)),
        q.nfcall(bump, Object.assign({ type: 'major'}, opts))
    ])
    .spread(function(rc, sub, patch, minor, major) {
        return { rc, sub, patch, minor, major }
    })
}

function prompt(versions) {
    return inquirer.prompt([
        {
            name: "version",
            type: "list",
            choices: [{
                name: `sub-release (${ versions.sub.new })`,
                value: versions.sub
            }, {
                name: `release-candidate (${ versions.rc.new })`,
                value: versions.rc
            }, {
                name: `patch (${ versions.patch.new })`,
                value: versions.patch
            }, {
                name: `minor (${ versions.minor.new })`,
                value: versions.minor
            }, {
                name: `major (${ versions.major.new })`,
                value: versions.major
            }],
            default: versions.patch,
            message: "What kind of release is it?"
        }
    ])
    .then(function(answers) { return answers.version })
}

function bump_version(version) {
    return q.nfcall(fs.writeFile, PACKAGE_PATH, version.str)
    .then(function() { return version })
}

function changelog(version) {
    if (version.preid === RC_PREID) return version
    let defer = q.defer()
    let file = fs.readFileSync(CHANGELOG_PATH)
    standardChangelog.createIfMissing()
    standardChangelog()
        .pipe(concatStream({ encoding: 'buffer'}, function(data) {
            fs.writeFileSync(CHANGELOG_PATH, Buffer.concat([data, file]))
            defer.resolve(version)
        }))

    return defer.promise
}

function git_commit(version) {
    let defer = q.defer()
    exec([
        'git add package.json CHANGELOG.md',
        `git commit -a -m "chore(release): v${ version.new }"`
    ].join(' && '), function(err) {
        if (err) return defer.reject(err)
        defer.resolve(version)
    })
    return defer.promise
}

function git_push(version) {
    let defer = q.defer()
    exec('git push', function(err) {
        if (err) return defer.reject(err)
        defer.resolve(version)
    })
    return defer.promise
}

function git_tag(version) {
    if (version.preid === RC_PREID) return version
    let defer = q.defer()
    exec([
        `git tag ${ version.new }`,
        'git push --tags'
    ].join(' && '), function(err) {
        if (err) return defer.reject(err)
        defer.resolve(version)
    })
    return defer.promise
}

function github_release(version) {
    if (version.preid === RC_PREID) return version
    if (!process.env.GITHUB_AUTH_TOKEN) {
        console.log('Cannot run conventionalGithubReleaser. You must add a .env file with a GITHUB_AUTH_TOKEN key')
        return version
    }
    const GITHUB_AUTH = {
        type: 'oauth',
        token: process.env.GITHUB_AUTH_TOKEN
    }
    return q.nfcall(conventionalGithubReleaser, GITHUB_AUTH, { preset: 'angular' })
}

get_all_versions()
.then(prompt)
.then(bump_version)
.then(changelog)
.then(git_commit)
.then(git_push)
.then(git_tag)
// .then(github_release)
.catch(function(err) {
    console.log(err)
})
<commit_msg>chore: use arrow function<commit_after>require('dotenv').config({ path: `${ process.env.PWD }/.env` })

const standardChangelog = require('standard-changelog')
    , conventionalGithubReleaser = require('conventional-github-releaser')
    , bump = require('bump-regex')
    , inquirer = require('inquirer')
    , fs = require('fs')
    , q = require('q')
    , exec = require('child_process').exec
    , concatStream = require('concat-stream')

const PACKAGE_PATH = `${ process.env.PWD }/package.json`
    , CHANGELOG_PATH = `${ process.env.PWD }/CHANGELOG.md`
    , RC_PREID = 'rc'

const VERSION = require(PACKAGE_PATH).version

function get_all_versions() {
    const opts = {
        str: fs.readFileSync(PACKAGE_PATH).toString()
    }
    const sub_opts = {
        str: (() => {
            if (VERSION.match(/-\d+$/)) return opts.str
            return opts.str.replace(
                /"version":\s*".*",?/,
                `"version": "${ VERSION }-0"`
            )
        })()
    }
    return q.all([
        q.nfcall(bump, Object.assign({ type: 'prerelease', preid: RC_PREID }, opts)),
        q.nfcall(bump, Object.assign({ type: 'prerelease' }, sub_opts)),
        q.nfcall(bump, Object.assign({ type: 'patch' }, opts)),
        q.nfcall(bump, Object.assign({ type: 'minor' }, opts)),
        q.nfcall(bump, Object.assign({ type: 'major'}, opts))
    ])
    .spread((rc, sub, patch, minor, major) => {
        return { rc, sub, patch, minor, major }
    })
}

function prompt(versions) {
    return inquirer.prompt([
        {
            name: "version",
            type: "list",
            choices: [{
                name: `sub-release (${ versions.sub.new })`,
                value: versions.sub
            }, {
                name: `release-candidate (${ versions.rc.new })`,
                value: versions.rc
            }, {
                name: `patch (${ versions.patch.new })`,
                value: versions.patch
            }, {
                name: `minor (${ versions.minor.new })`,
                value: versions.minor
            }, {
                name: `major (${ versions.major.new })`,
                value: versions.major
            }],
            default: versions.patch,
            message: "What kind of release is it?"
        }
    ])
    .then((answers) => answers.version)
}

function bump_version(version) {
    return q.nfcall(fs.writeFile, PACKAGE_PATH, version.str)
    .then(() => version)
}

function changelog(version) {
    if (version.preid === RC_PREID) return version
    let defer = q.defer()
    let file = fs.readFileSync(CHANGELOG_PATH)
    standardChangelog.createIfMissing()
    standardChangelog()
        .pipe(concatStream({ encoding: 'buffer'}, (data) => {
            fs.writeFileSync(CHANGELOG_PATH, Buffer.concat([data, file]))
            defer.resolve(version)
        }))

    return defer.promise
}

function git_commit(version) {
    let defer = q.defer()
    exec([
        'git add package.json CHANGELOG.md',
        `git commit -a -m "chore(release): v${ version.new }"`
    ].join(' && '), (err) => {
        if (err) return defer.reject(err)
        defer.resolve(version)
    })
    return defer.promise
}

function git_push(version) {
    let defer = q.defer()
    exec('git push', (err) => {
        if (err) return defer.reject(err)
        defer.resolve(version)
    })
    return defer.promise
}

function git_tag(version) {
    if (version.preid === RC_PREID) return version
    let defer = q.defer()
    exec([
        `git tag ${ version.new }`,
        'git push --tags'
    ].join(' && '), (err) => {
        if (err) return defer.reject(err)
        defer.resolve(version)
    })
    return defer.promise
}

function github_release(version) {
    if (version.preid === RC_PREID) return version
    if (!process.env.GITHUB_AUTH_TOKEN) {
        console.log('Cannot run conventionalGithubReleaser. You must add a .env file with a GITHUB_AUTH_TOKEN key')
        return version
    }
    const GITHUB_AUTH = {
        type: 'oauth',
        token: process.env.GITHUB_AUTH_TOKEN
    }
    return q.nfcall(conventionalGithubReleaser, GITHUB_AUTH, { preset: 'angular' })
}

get_all_versions()
.then(prompt)
.then(bump_version)
.then(changelog)
.then(git_commit)
.then(git_push)
.then(git_tag)
// .then(github_release)
.catch((err) => {
    console.log(err)
})
<|endoftext|>


<commit_before>'use strict';

var cocktail = require('cocktail');
var spawn    = require('child_process').spawn;

cocktail.mix({
    '@exports': module,
    '@as': 'class',

    '@requires': [
        'getArgs'
    ],

    runSpawn: function (which, args) {
        this._attachSpawnListeners(spawn(which, args));
    },

    _attachSpawnListeners: function (spawnInstance) {
        var me = this;
        me._attachEventListener('data', spawnInstance.stdout, me._onProgress);
        me._attachEventListener('error', spawnInstance.stderr, me._onError);
    },

   _attachEventListener: function (event, stream, mthd) {
        stream.on(event, mthd.bind(this));
    },

    _onProgress: function (data) {
        console.log('' + data);
    },

    _onError: function (data) {
        console.error('Error: ' + data);
    }
});
<commit_msg>output cmd process on stdout. Preserved colored output.<commit_after>'use strict';

var cocktail = require('cocktail');
var spawn    = require('child_process').spawn;

cocktail.mix({
    '@exports': module,
    '@as': 'class',

    runSpawn: function (which, args) {
        spawn(which, args, {stdio: "inherit"});
    }

});
<|endoftext|>


<commit_before>var argv = require('optimist').argv;
var _ = require('underscore');
var Backbone = require('backbone');
var smsd = require('../sms/index').reader;
var dirty = require('dirty');
var db = dirty(argv.shoppingdb || './data/list.db');
var db2 = dirty(argv.shoppingdb || './data/hashes.db');

// TESTE TASKS

if (argv.test) {

	var task = detectTask('Kaufe am Do 3x Butter bei Aldi Hohe Str');
	console.log(task);

	var task = detectTask('Einkauf am Do bei Aldi Hohe Str?');
	console.log(task);

	var task = detectTask('Geschäft Aldi Hohe Str?');
	console.log(task);

}

var Item = Backbone.Model.extend({
	defaults: {
		due: null,
		quantity: 1,
		product: '',
		trader: '',
		store: '',
        origin: ''
	}
});

var Items = Backbone.Collection.extend({
	model: Item
});

var list = new Items();
var hashes = [];

if (argv.try) {

    loadData(function dataLoaded() {
        var isDataChanged = executeTask( detectTask(argv.try) );
        if (isDataChanged) {
            saveData();
        }
    });

} else {

    initialize();

}

function initialize () {
	loadData(function dataLoaded() {
		readTasks(function(tasks){
            var isDataChanged = false;
            console.log(tasks);
			for (var i=0; i<tasks.length; i++) {
                isDataChanged = isDataChanged || executeTask(tasks[i]);
                if (i === tasks.length-1 && isDataChanged) {
                    saveData();
                }
			}
		});
	});
}

function readTasks (callback) {
	var tasks = [];
	smsd.readMessages(function filterMessages(storedMessages) {
        var newMessageDetected = false;
		storedMessages.forEach(function (message) {
            if (hashes && hashes.length>0 && _.indexOf(hashes, message.get('hash'))>-1) {
                // ignore message
                console.log("ignore " + message.get('hash'));
            } else {
                newMessageDetected = true;
                hashes.push(message.get('hash'));
                var task = detectTask(message.get('message'));
                if (!_.isEmpty(task)) {
                    tasks.push(task);
                }
            }
		});
        if (newMessageDetected) {
            //saveHashes(); // disable for testing get commands
        }
		callback(tasks);
	});
}

function executeTask (task) {
    var isDataChanged = false;
	console.log("execute: " + task.origin);
    console.log(task);
	switch (task.command) {
		case 'add':
            isDataChanged = true;
			list.add({
				due: task.due,
				quantity: task.quantity || 1,
				product: task.product,
				trader: task.trader || '',
				store: task.store || '',
                origin: task.origin
			});
			break;
		case 'get':
			var filter = {};
            var matchGiven = [];
			if (task.due) filter.due = task.due;
            if (task.trader) {
                console.log("add trader filter");
                filter.trader = task.trader;
            }
			if (task.store) filter.store = task.store;
            if (_.isEmpty(filter)) {
                matchGiven = list;
            } else {
                matchGiven = list.where(filter);
            }
            if (task.trader) {
                filter.trader = '';
                var matchAny = list.where(filter);
                matchGiven = _.union(matchGiven, matchAny);
            }
//			console.log("match...");
//			console.log(JSON.stringify(match));
            reply(matchGiven);
			break;
	}
    return isDataChanged;
}

function reply (collection) {
    var messages = [];
    collection.forEach(function (model){
        messages.push(model.get('product'));
    });
    var text = messages.join(', ');
    console.log(text);
}

function loadData (callback) {
	db.on('load', function() {
		list = new Items(db.get('list') || []);
        hashes = db2.get('hashes') || [];
		callback();
	});
}

function saveHashes () {
    db2.set("hashes", hashes, function hashesSaved (){
    });
}

function saveData () {
	db.set("list", list, function listSaved (){
        console.log("list saved..");
//        console.log(list);
	});
}

function detectTask (message) {

	var tasks = {
		'add': 'kaufe( am [a-z]{0,2}){0,1}( [0-9]{1,3}x){0,1}( [a-z]{3,})( bei [a-z]{3,}){0,1}( [a-z ]{3,}){0,1}',
		'get': 'einkauf( am [a-z]{0,2}){0,1}( bei [a-z]{3,}){0,1}( [a-z ]{3,}){0,1}\\?',
		'info': 'geschäft( [a-z]{3,}){0,1}( [a-z ]{3,}){0,1}\\?'
	};

	var task = {};

	for (var t in tasks) {

		var taskreg = new RegExp(tasks[t],'i');
		var matcher = message.match(taskreg);
		if (matcher) {
			// fix undefined parts to an empty string
			for (var i=0; i<matcher.length; i++) {
				matcher[i] = matcher[i] || ''
			}
			//console.log(matcher);
			if (matcher.length>1) {
				switch (t) {
					case 'add':
						task = {
							command: t,
							due: matcher[1].replace(/ am /,''),
							quantity: matcher[2].replace(/ /g,'').replace(/x/,'') || 1,
							product: matcher[3].replace(/ /g,''),
							trader: matcher[4].replace(/ bei /g,''),
							store: matcher[5].replace(/^ /g,''),
                            origin: message
						};
						if (!task.product || task.product === 'bei') {
							throw Error('Product required');
						}
						break;
					case 'get':
						task = {
							command: t,
							due: matcher[1].replace(/ am /,''),
							trader: matcher[2].replace(/ bei /g,''),
							store: matcher[3].replace(/^ /g,''),
                            origin: message
						};
						break;
					case 'info':
						task = {
							command: t,
							trader: matcher[1].replace(/ /g,''),
							store: matcher[2].replace(/^ /g,''),
                            origin: message
						};
						break;
				}
				if (!task.command) {
					throw Error('Task required');
				}
				return task;
			}
		}
	}

	return task;
}		<commit_msg>Integration reply by sms<commit_after>var argv = require('optimist').argv;
var _ = require('underscore');
var Backbone = require('backbone');
var smsd = require('../sms/index');
var dirty = require('dirty');
var db = dirty(argv.shoppingdb || './data/list.db');
var db2 = dirty(argv.shoppingdb || './data/hashes.db');

// TESTE TASKS

if (argv.test) {

	var task = detectTask('Kaufe am Do 3x Butter bei Aldi Hohe Str');
	console.log(task);

	var task = detectTask('Einkauf am Do bei Aldi Hohe Str?');
	console.log(task);

	var task = detectTask('Geschäft Aldi Hohe Str?');
	console.log(task);

}

var Item = Backbone.Model.extend({
	defaults: {
		due: null,
		quantity: 1,
		product: '',
		trader: '',
		store: '',
        origin: ''
	}
});

var Items = Backbone.Collection.extend({
	model: Item
});

var list = new Items();
var hashes = [];
var phoneNumber = null;

if (argv.try) {

    loadData(function dataLoaded() {
        var isDataChanged = executeTask( detectTask(argv.try) );
        if (isDataChanged) {
            saveData();
        }
    });

} else {

    initialize();

}

function initialize () {
	loadData(function dataLoaded() {
		readTasks(function(tasks){
            var isDataChanged = false;
            console.log(tasks);
			for (var i=0; i<tasks.length; i++) {
                isDataChanged = isDataChanged || executeTask(tasks[i]);
                if (i === tasks.length-1 && isDataChanged) {
                    saveData();
                }
			}
		});
	});
}

function readTasks (callback) {
	var tasks = [];
	smsd.reader.readMessages(function filterMessages(storedMessages) {
        var newMessageDetected = false;
		storedMessages.forEach(function (message) {
            if (hashes && hashes.length>0 && _.indexOf(hashes, message.get('hash'))>-1) {
                // ignore message
                console.log("ignore " + message.get('hash'));
            } else {
                newMessageDetected = true;
                hashes.push(message.get('hash'));
                var task = detectTask(message.get('message'));
                if (!_.isEmpty(task)) {
                    tasks.push(task);
                }
            }
		});
        if (newMessageDetected) {
            //saveHashes(); // disable for testing get commands
        }
		callback(tasks);
	});
}

function executeTask (task) {
    var isDataChanged = false;
	console.log("execute: " + task.origin);
    //console.log(task);
	phoneNumber = task.phoneNumber;
	switch (task.command) {
		case 'add':
            isDataChanged = true;
			list.add({
				due: task.due,
				quantity: task.quantity || 1,
				product: task.product,
				trader: task.trader || '',
				store: task.store || '',
                origin: task.origin
			});
			break;
		case 'get':
			var filter = {};
            var matchGiven = [];
			if (task.due) filter.due = task.due;
            if (task.trader) {
                console.log("add trader filter");
                filter.trader = task.trader;
            }
			if (task.store) filter.store = task.store;
            if (_.isEmpty(filter)) {
                matchGiven = list;
            } else {
                matchGiven = list.where(filter);
            }
            if (task.trader) {
                filter.trader = '';
                var matchAny = list.where(filter);
                matchGiven = _.union(matchGiven, matchAny);
            }
//			console.log("match...");
//			console.log(JSON.stringify(match));
            reply(matchGiven);
			break;
	}
    return isDataChanged;
}

function reply (collection) {
    var messages = [];
    collection.forEach(function (model){
        messages.push(model.get('product'));
    });
    var text = messages.join(', ');
    submitReply(phoneNumber, text);
}

function submitReply (to, message) {
	if (to && message) {
		console.log("reply to " + to + ": " + message);
		smsd.sender.sendMessage({
			to: to,
			message: message,
			success: function(response) {
				//console.log(response);
			}
		});
	}
}

function loadData (callback) {
	db.on('load', function() {
		list = new Items(db.get('list') || []);
        hashes = db2.get('hashes') || [];
		callback();
	});
}

function saveHashes () {
    db2.set("hashes", hashes, function hashesSaved (){
    });
}

function saveData () {
	db.set("list", list, function listSaved (){
        console.log("list saved..");
//        console.log(list);
	});
}

function detectTask (message) {

	var tasks = {
		'add': 'kaufe( am [a-z]{0,2}){0,1}( [0-9]{1,3}x){0,1}( [a-z]{3,})( bei [a-z]{3,}){0,1}( [a-z ]{3,}){0,1}',
		'get': 'einkauf( am [a-z]{0,2}){0,1}( bei [a-z]{3,}){0,1}( [a-z ]{3,}){0,1}\\?',
		'info': 'geschäft( [a-z]{3,}){0,1}( [a-z ]{3,}){0,1}\\?'
	};

	var task = {};

	for (var t in tasks) {

		var taskreg = new RegExp(tasks[t],'i');
		var matcher = message.match(taskreg);
		if (matcher) {
			// fix undefined parts to an empty string
			for (var i=0; i<matcher.length; i++) {
				matcher[i] = matcher[i] || ''
			}
			//console.log(matcher);
			if (matcher.length>1) {
				switch (t) {
					case 'add':
						task = {
							command: t,
							due: matcher[1].replace(/ am /,''),
							quantity: matcher[2].replace(/ /g,'').replace(/x/,'') || 1,
							product: matcher[3].replace(/ /g,''),
							trader: matcher[4].replace(/ bei /g,''),
							store: matcher[5].replace(/^ /g,''),
                            origin: message
						};
						if (!task.product || task.product === 'bei') {
							throw Error('Product required');
						}
						break;
					case 'get':
						task = {
							command: t,
							due: matcher[1].replace(/ am /,''),
							trader: matcher[2].replace(/ bei /g,''),
							store: matcher[3].replace(/^ /g,''),
                            origin: message
						};
						break;
					case 'info':
						task = {
							command: t,
							trader: matcher[1].replace(/ /g,''),
							store: matcher[2].replace(/^ /g,''),
                            origin: message
						};
						break;
				}
				if (!task.command) {
					throw Error('Task required');
				}
				return task;
			}
		}
	}

	return task;
}		<|endoftext|>


<commit_before>var url = require("url");
var fs = require("fs");
var Assets = require("./lib/assets");

var connectAssets = module.exports = function (options) {
  options = parseOptions(options || {});

  var assets = new Assets(options);
  var compilationComplete = false;
  var compilationError;
  var waiting = [];

  options.helperContext.css = assets.helper(tagWriters.css, "css");
  options.helperContext.js = assets.helper(tagWriters.js, "js");
  options.helperContext.assetPath = assets.helper(tagWriters.noop);

  assets.compile(function (err) {
    if (err) { compilationError = err; }
    compilationComplete = true;

    for (var i = 0; i < waiting.length; i++) {
      waiting[i]();
    };
  });

  var middleware = function (req, res, next) {
    var path = parseUrl(req.url).pathname.replace(/^\//, "");

    if (path.toLowerCase().indexOf(options.localServePath.toLowerCase()) === 0) {
      var serve = function (req, res, next) {
        if (compilationError) { next(compilationError); }
        else { assets.serveAsset(req, res, next); }
      };

      if (compilationComplete) { serve(req, res, next); }
      else { waiting.push(serve.bind(this, req, res, next)); }
    }
    else {
      next();
    }
  };

  Object.keys(assets).forEach(function (method) {
    middleware[method] = assets[method];
  });

  Object.keys(assets.__proto__).forEach(function (method) {
    middleware.__proto__[method] = assets.__proto__[method];
  });

  return middleware;
};

var parseOptions = module.exports._parseOptions = function (options) {
  var isProduction = process.env.NODE_ENV === "production";
  var isDevelopment = !isProduction;

  options.paths = arrayify(options.paths || options.src || [ "assets/js", "assets/css" ]);
  options.helperContext = options.helperContext || global;
  options.servePath = (options.servePath || "assets");
  options.localServePath = options.localServePath || parseUrl(options.servePath).pathname.replace(/^\//, "");
  options.servePath = options.servePath.replace(/^\//, "").replace(/\/$/, "");
  options.precompile = arrayify(options.precompile || ["*.*"]);
  options.build = options.build != null ? options.build : isProduction;
  options.buildDir = options.buildDir != null ? options.buildDir : isDevelopment ? false : "builtAssets";
  options.compile = options.compile != null ? options.compile : true;
  options.compress = options.compress != null ? options.compress : isProduction;
  options.gzip = options.gzip != null ? options.gzip : false;

  if (options.buildDir.replace) {
    options.buildDir = options.buildDir.replace(/^\//, "").replace(/\/$/, "");
  }

  return options;
};

var arrayify = module.exports._arrayify = function (target) {
  return (target instanceof Array) ? target : [ target ];
};

var pasteAttr = function (attributes) {
  return !!attributes ? ' ' + attributes : '';
};

var parseUrl = function (string) {
  var parseQueryString = false;
  var allowUrlWithoutProtocol = true;
  return url.parse(string, parseQueryString, allowUrlWithoutProtocol);
};

var tagWriters = {
  css: function (url, attr) { return '<link rel="stylesheet" href="' + url + '"' + pasteAttr(attr) + ' />'; },
  js: function (url, attr) { return '<script src="' + url + '"' + pasteAttr(attr) + '></script>'; },
  noop: function (url) { return url; }
};
<commit_msg>Define options.servePath only once.<commit_after>var url = require("url");
var fs = require("fs");
var Assets = require("./lib/assets");

var connectAssets = module.exports = function (options) {
  options = parseOptions(options || {});

  var assets = new Assets(options);
  var compilationComplete = false;
  var compilationError;
  var waiting = [];

  options.helperContext.css = assets.helper(tagWriters.css, "css");
  options.helperContext.js = assets.helper(tagWriters.js, "js");
  options.helperContext.assetPath = assets.helper(tagWriters.noop);

  assets.compile(function (err) {
    if (err) { compilationError = err; }
    compilationComplete = true;

    for (var i = 0; i < waiting.length; i++) {
      waiting[i]();
    };
  });

  var middleware = function (req, res, next) {
    var path = parseUrl(req.url).pathname.replace(/^\//, "");

    if (path.toLowerCase().indexOf(options.localServePath.toLowerCase()) === 0) {
      var serve = function (req, res, next) {
        if (compilationError) { next(compilationError); }
        else { assets.serveAsset(req, res, next); }
      };

      if (compilationComplete) { serve(req, res, next); }
      else { waiting.push(serve.bind(this, req, res, next)); }
    }
    else {
      next();
    }
  };

  Object.keys(assets).forEach(function (method) {
    middleware[method] = assets[method];
  });

  Object.keys(assets.__proto__).forEach(function (method) {
    middleware.__proto__[method] = assets.__proto__[method];
  });

  return middleware;
};

var parseOptions = module.exports._parseOptions = function (options) {
  var isProduction = process.env.NODE_ENV === "production";
  var isDevelopment = !isProduction;
  var servePath = (options.servePath || "assets");

  options.paths = arrayify(options.paths || options.src || [ "assets/js", "assets/css" ]);
  options.helperContext = options.helperContext || global;
  options.servePath = servePath.replace(/^\//, "").replace(/\/$/, "");
  options.localServePath = options.localServePath || parseUrl(servePath).pathname.replace(/^\//, "");
  options.precompile = arrayify(options.precompile || ["*.*"]);
  options.build = options.build != null ? options.build : isProduction;
  options.buildDir = options.buildDir != null ? options.buildDir : isDevelopment ? false : "builtAssets";
  options.compile = options.compile != null ? options.compile : true;
  options.compress = options.compress != null ? options.compress : isProduction;
  options.gzip = options.gzip != null ? options.gzip : false;

  if (options.buildDir.replace) {
    options.buildDir = options.buildDir.replace(/^\//, "").replace(/\/$/, "");
  }

  return options;
};

var arrayify = module.exports._arrayify = function (target) {
  return (target instanceof Array) ? target : [ target ];
};

var pasteAttr = function (attributes) {
  return !!attributes ? ' ' + attributes : '';
};

var parseUrl = function (string) {
  var parseQueryString = false;
  var allowUrlWithoutProtocol = true;
  return url.parse(string, parseQueryString, allowUrlWithoutProtocol);
};

var tagWriters = {
  css: function (url, attr) { return '<link rel="stylesheet" href="' + url + '"' + pasteAttr(attr) + ' />'; },
  js: function (url, attr) { return '<script src="' + url + '"' + pasteAttr(attr) + '></script>'; },
  noop: function (url) { return url; }
};
<|endoftext|>


<commit_before>function argString(args) {
  var asStrings = [];

  for (i = 0; i < args.length; i++) {
    if (typeof args[i] === 'string') {
      asStrings.push('\'' + args[i] + '\'');
    } else {
      asStrings.push(args[i]);
    }
  }

  return asStrings.join(', ');
}

function unexpectedFunctionCall(mock, args) {
  return new Error('unexpected function call ' + mock._name + '(' + argString(args) + ')');
}

function defaultMockHandler() {
  throw unexpectedFunctionCall(this, Array.prototype.slice.call(arguments));
}

var mockHandler = defaultMockHandler;

function ExpectedCall(mock, args) {
  return {
    mock: mock,
    met: false,
    args: args || [],
    complete: function() {
      this.met = true;
    },
    isComplete: function() {
      return this.met;
    },
    matches: function(mock, args) {
      if (mock === this.mock) {
        if (args.length !== this.args.length) {
          return false;
        }

        for (i = 0; i < args.length; i++) {
          if (args[i] !== this.args[i]) {
            return false;
          }
        }

        return true;
      }
    }
  };
}

function Expectation() {
  var expectedCalls = [];

  function when(thunk) {
    mockHandler = function mockHandler() {
      var mock = this;
      var matchedExpectation;
      var args = Array.prototype.slice.call(arguments);

      expectedCalls.some(function(expectedCall) {
        if (expectedCall.matches(mock, args)) {
          expectedCall.complete();
          matchedExpectation = expectedCall;
          return true;
        }

        return false;
      });

      if (!matchedExpectation) {
        throw unexpectedFunctionCall(mock, args);
      }

      return matchedExpectation.returnValue;
    }

    thunk();

    mockHandler = defaultMockHandler;

    expectedCalls.forEach(function(expectedCall) {
      if (expectedCall.isComplete() == false) {
        throw new Error('not all calls occurred');
      }
    });
  }

  function andWillReturn(returnValue) {
    expectedCalls[expectedCalls.length - 1].returnValue = returnValue;
    return this;
  }

  function andAlso(expectation) {
    expectation._expectedCalls.forEach(function(expectedCall) {
      expectedCalls.push(expectedCall);
    });

    return this;
  }

  function expectCallTo(mock, args) {
    expectation._expectedCalls.push(ExpectedCall(theMock), args);
  }

  return {
    when: when,
    andWillReturn: andWillReturn,
    andAlso: andAlso,
    _expectedCalls: expectedCalls,
    _expectCallTo: expectCallTo
  };
}

module.exports = {
  mockFunction: function mockFunction(name) {
    var theMock = function theMock() {
      return mockHandler.apply(theMock, Array.prototype.slice.call(arguments));
    };

    theMock._name = name;

    theMock.shouldBeCalled = function shouldBeCalled() {
      var expectation = Expectation();
      expectation.expectCallTo(theMock);
      return expectation;
    };

    theMock.shouldBeCalledWith = function shouldBeCalledWith() {
      var expectation = Expectation();
      expectation.expectCallTo(theMock, Array.prototype.slice.call(arguments));
      return expectation;
    }

    return theMock;
  }
};
<commit_msg>Extracted Mock<commit_after>function argString(args) {
  var asStrings = [];

  for (i = 0; i < args.length; i++) {
    if (typeof args[i] === 'string') {
      asStrings.push('\'' + args[i] + '\'');
    } else {
      asStrings.push(args[i]);
    }
  }

  return asStrings.join(', ');
}

function unexpectedFunctionCall(mock, args) {
  return new Error('unexpected function call ' + mock._name + '(' + argString(args) + ')');
}

function defaultMockHandler() {
  throw unexpectedFunctionCall(this, Array.prototype.slice.call(arguments));
}

var mockHandler = defaultMockHandler;

function ExpectedCall(mock, args) {
  return {
    mock: mock,
    met: false,
    args: args || [],
    complete: function() {
      this.met = true;
    },
    isComplete: function() {
      return this.met;
    },
    matches: function(mock, args) {
      if (mock === this.mock) {
        if (args.length !== this.args.length) {
          return false;
        }

        for (i = 0; i < args.length; i++) {
          if (args[i] !== this.args[i]) {
            return false;
          }
        }

        return true;
      }
    }
  };
}

function Expectation() {
  var expectedCalls = [];

  function when(thunk) {
    mockHandler = function mockHandler() {
      var mock = this;
      var matchedExpectation;
      var args = Array.prototype.slice.call(arguments);

      expectedCalls.some(function(expectedCall) {
        if (expectedCall.matches(mock, args)) {
          expectedCall.complete();
          matchedExpectation = expectedCall;
          return true;
        }

        return false;
      });

      if (!matchedExpectation) {
        throw unexpectedFunctionCall(mock, args);
      }

      return matchedExpectation.returnValue;
    }

    thunk();

    mockHandler = defaultMockHandler;

    expectedCalls.forEach(function(expectedCall) {
      if (expectedCall.isComplete() == false) {
        throw new Error('not all calls occurred');
      }
    });
  }

  function andWillReturn(returnValue) {
    expectedCalls[expectedCalls.length - 1].returnValue = returnValue;
    return this;
  }

  function andAlso(expectation) {
    expectation._expectedCalls.forEach(function(expectedCall) {
      expectedCalls.push(expectedCall);
    });

    return this;
  }

  function expectCallTo(mock, args) {
    this._expectedCalls.push(ExpectedCall(mock, args));
  }

  return {
    when: when,
    andWillReturn: andWillReturn,
    andAlso: andAlso,
    _expectedCalls: expectedCalls,
    _expectCallTo: expectCallTo
  };
}

function Mock(name) {
  var mock = function mock() {
    return mockHandler.apply(mock, Array.prototype.slice.call(arguments));
  };

  mock._name = name;

  mock.shouldBeCalled = function shouldBeCalled() {
    var expectation = Expectation();
    expectation._expectCallTo(mock);
    return expectation;
  };

  mock.shouldBeCalledWith = function shouldBeCalledWith() {
    var expectation = Expectation();
    expectation._expectCallTo(mock, Array.prototype.slice.call(arguments));
    return expectation;
  }

  return mock;
}

module.exports = {
  mockFunction: function mockFunction(name) {
    return Mock(name);
  }
};
<|endoftext|>


<commit_before>var errors = require('./errors')
var native = require('./native')

// short-hand
var tfJSON = errors.tfJSON
var stfJSON = errors.stfJSON
var TfTypeError = errors.TfTypeError
var TfPropertyTypeError = errors.TfPropertyTypeError
var tfSubError = errors.tfSubError
var getValueTypeName = errors.getValueTypeName

var types = {
  arrayOf: function arrayOf (type) {
    type = compile(type)

    function arrayOf (array, strict) {
      if (!native.Array(array)) return false

      return array.every(function (value, i) {
        try {
          return typeforce(type, value, strict)
        } catch (e) {
          throw tfSubError(e, i)
        }
      })
    }
    arrayOf.toJSON = function () { return [tfJSON(type)] }

    return arrayOf
  },

  maybe: function maybe (type) {
    type = compile(type)

    function maybe (value, strict) {
      return native.Null(value) || type(value, strict, maybe)
    }
    maybe.toJSON = function () { return '?' + stfJSON(type) }

    return maybe
  },

  object: function object (type) {
    function object (value, strict) {
      if (!native.Object(value)) return false
      if (native.Null(value)) return false

      var propertyName

      try {
        for (propertyName in type) {
          var propertyType = type[propertyName]
          var propertyValue = value[propertyName]

          typeforce(propertyType, propertyValue, strict)
        }
      } catch (e) {
        throw tfSubError(e, propertyName)
      }

      if (strict) {
        for (propertyName in value) {
          if (type[propertyName]) continue

          throw new TfPropertyTypeError(undefined, propertyName)
        }
      }

      return true
    }
    object.toJSON = function () { return tfJSON(type) }

    return object
  },

  map: function map (propertyType, propertyKeyType) {
    propertyType = compile(propertyType)
    if (propertyKeyType) propertyKeyType = compile(propertyKeyType)

    function map (value, strict) {
      if (!native.Object(value, strict)) return false
      if (native.Null(value, strict)) return false

      for (var propertyName in value) {
        try {
          if (propertyKeyType) {
            typeforce(propertyKeyType, propertyName, strict)
          }
        } catch (e) {
          throw tfSubError(e, propertyName, 'key')
        }

        try {
          var propertyValue = value[propertyName]
          typeforce(propertyType, propertyValue, strict)
        } catch (e) {
          throw tfSubError(e, propertyName)
        }
      }

      return true
    }

    if (propertyKeyType) {
      map.toJSON = function () {
        return '{' + stfJSON(propertyKeyType) + ': ' + stfJSON(propertyType) + '}'
      }
    } else {
      map.toJSON = function () { return '{' + stfJSON(propertyType) + '}' }
    }

    return map
  },

  oneOf: function oneOf () {
    var types = [].slice.call(arguments).map(compile)

    function oneOf (value, strict) {
      return types.some(function (type) {
        return type(value, strict)
      })
    }
    oneOf.toJSON = function () { return types.map(stfJSON).join('|') }

    return oneOf
  },

  quacksLike: function quacksLike (type) {
    function quacksLike (value) {
      return type === getValueTypeName(value)
    }
    quacksLike.toJSON = function () { return type }

    return quacksLike
  },

  tuple: function tuple () {
    var types = [].slice.call(arguments).map(compile)

    function tuple (values, strict) {
      return types.every(function (type, i) {
        try {
          return typeforce(type, values[i], strict)
        } catch (e) {
          throw tfSubError(e, i)
        }
      })
    }
    tuple.toJSON = function () { return '(' + types.map(stfJSON).join(', ') + ')' }

    return tuple
  },

  value: function value (expected) {
    function value (actual) {
      return actual === expected
    }
    value.toJSON = function () { return expected }

    return value
  }
}

function compile (type) {
  if (native.String(type)) {
    if (type[0] === '?') return types.maybe(compile(type.slice(1)))

    return native[type] || types.quacksLike(type)
  } else if (type && native.Object(type)) {
    if (native.Array(type)) return types.arrayOf(compile(type[0]))

    var compiled = {}

    for (var propertyName in type) {
      compiled[propertyName] = compile(type[propertyName])
    }

    return types.object(compiled)
  } else if (native.Function(type)) {
    return type
  }

  return types.value(type)
}

function typeforce (type, value, strict, surrogate) {
  if (native.Function(type)) {
    if (type(value, strict)) return true

    throw new TfTypeError(surrogate || type, value)
  }

  // JIT
  return typeforce(compile(type), value, strict)
}

// assign types to typeforce function
for (var typeName in native) {
  typeforce[typeName] = native[typeName]
}

for (typeName in types) {
  typeforce[typeName] = types[typeName]
}

var extra = require('./extra')
for (typeName in extra) {
  typeforce[typeName] = extra[typeName]
}

typeforce.compile = compile
typeforce.TfTypeError = TfTypeError
typeforce.TfPropertyTypeError = TfPropertyTypeError

module.exports = typeforce
<commit_msg>rm object, too ambiguous, fixes #40<commit_after>var errors = require('./errors')
var native = require('./native')

// short-hand
var tfJSON = errors.tfJSON
var stfJSON = errors.stfJSON
var TfTypeError = errors.TfTypeError
var TfPropertyTypeError = errors.TfPropertyTypeError
var tfSubError = errors.tfSubError
var getValueTypeName = errors.getValueTypeName

function schema (type) {
  function schema (value, strict) {
    if (!native.Object(value)) return false
    if (native.Null(value)) return false

    var propertyName

    try {
      for (propertyName in type) {
        var propertyType = type[propertyName]
        var propertyValue = value[propertyName]

        typeforce(propertyType, propertyValue, strict)
      }
    } catch (e) {
      throw tfSubError(e, propertyName)
    }

    if (strict) {
      for (propertyName in value) {
        if (type[propertyName]) continue

        throw new TfPropertyTypeError(undefined, propertyName)
      }
    }

    return true
  }
  schema.toJSON = function () { return tfJSON(type) }

  return schema
}

var types = {
  arrayOf: function arrayOf (type) {
    type = compile(type)

    function arrayOf (array, strict) {
      if (!native.Array(array)) return false

      return array.every(function (value, i) {
        try {
          return typeforce(type, value, strict)
        } catch (e) {
          throw tfSubError(e, i)
        }
      })
    }
    arrayOf.toJSON = function () { return [tfJSON(type)] }

    return arrayOf
  },

  maybe: function maybe (type) {
    type = compile(type)

    function maybe (value, strict) {
      return native.Null(value) || type(value, strict, maybe)
    }
    maybe.toJSON = function () { return '?' + stfJSON(type) }

    return maybe
  },

  map: function map (propertyType, propertyKeyType) {
    propertyType = compile(propertyType)
    if (propertyKeyType) propertyKeyType = compile(propertyKeyType)

    function map (value, strict) {
      if (!native.Object(value, strict)) return false
      if (native.Null(value, strict)) return false

      for (var propertyName in value) {
        try {
          if (propertyKeyType) {
            typeforce(propertyKeyType, propertyName, strict)
          }
        } catch (e) {
          throw tfSubError(e, propertyName, 'key')
        }

        try {
          var propertyValue = value[propertyName]
          typeforce(propertyType, propertyValue, strict)
        } catch (e) {
          throw tfSubError(e, propertyName)
        }
      }

      return true
    }

    if (propertyKeyType) {
      map.toJSON = function () {
        return '{' + stfJSON(propertyKeyType) + ': ' + stfJSON(propertyType) + '}'
      }
    } else {
      map.toJSON = function () { return '{' + stfJSON(propertyType) + '}' }
    }

    return map
  },

  oneOf: function oneOf () {
    var types = [].slice.call(arguments).map(compile)

    function oneOf (value, strict) {
      return types.some(function (type) {
        return type(value, strict)
      })
    }
    oneOf.toJSON = function () { return types.map(stfJSON).join('|') }

    return oneOf
  },

  quacksLike: function quacksLike (type) {
    function quacksLike (value) {
      return type === getValueTypeName(value)
    }
    quacksLike.toJSON = function () { return type }

    return quacksLike
  },

  tuple: function tuple () {
    var types = [].slice.call(arguments).map(compile)

    function tuple (values, strict) {
      return types.every(function (type, i) {
        try {
          return typeforce(type, values[i], strict)
        } catch (e) {
          throw tfSubError(e, i)
        }
      })
    }
    tuple.toJSON = function () { return '(' + types.map(stfJSON).join(', ') + ')' }

    return tuple
  },

  value: function value (expected) {
    function value (actual) {
      return actual === expected
    }
    value.toJSON = function () { return expected }

    return value
  }
}

function compile (type) {
  if (native.String(type)) {
    if (type[0] === '?') return types.maybe(compile(type.slice(1)))

    return native[type] || types.quacksLike(type)
  } else if (type && native.Object(type)) {
    if (native.Array(type)) return types.arrayOf(compile(type[0]))

    var compiled = {}

    for (var propertyName in type) {
      compiled[propertyName] = compile(type[propertyName])
    }

    return schema(compiled)
  } else if (native.Function(type)) {
    return type
  }

  return types.value(type)
}

function typeforce (type, value, strict, surrogate) {
  if (native.Function(type)) {
    if (type(value, strict)) return true

    throw new TfTypeError(surrogate || type, value)
  }

  // JIT
  return typeforce(compile(type), value, strict)
}

// assign types to typeforce function
for (var typeName in native) {
  typeforce[typeName] = native[typeName]
}

for (typeName in types) {
  typeforce[typeName] = types[typeName]
}

var extra = require('./extra')
for (typeName in extra) {
  typeforce[typeName] = extra[typeName]
}

typeforce.compile = compile
typeforce.TfTypeError = TfTypeError
typeforce.TfPropertyTypeError = TfPropertyTypeError

module.exports = typeforce
<|endoftext|>


<commit_before><commit_msg>first working copy<commit_after>const express = require('express');
const request = require('request');
const bodyParser = require('body-parser');

const secret = process.env.SECRET || 'cf-secrets';
const token = process.env.TOKEN;

const app = express();
app.use(bodyParser.json());
app.all('/in', (req, res, next) => {
  console.log(req.headers);
  console.log(req.body);
  if (req.headers['x-github-event'] && req.headers['x-github-event'] === 'pull_request') {
    console.log(req.body.action);
    console.log(req.body.pull_request.merged);
  }
  if (req.headers['x-github-event'] && req.headers['x-github-event'] === 'push') {
    if (req.body.ref === 'refs/heads/master') {
      //pushing to master
      const newVersion = `v${1}`;
      request('https://api.github.com/repos/ajuhaszcf/webhook-test/releases', {
        auth: {
          user: 'ajuhaszcf',
          pass: token,
        },
        headers: {
          'Accept': ' application/vnd.github.v3+json',
          'User-Agent': 'CF-Webhook',
        },
        method: 'POST',
        json: true,
        body: {
          "tag_name": newVersion,
          "target_commitish": "master",
          "name": newVersion,
          "body": "Autorag of a new release",
          "draft": false,
          "prerelease": false
        },
      }, (error, response, body) => {
        if (error) {
          console.error(errot);
          return;
        }
        console.log('response', body);
      });
    }
  }
  res.status(200).end();
});
app.listen(process.env.PORT || 3000);<|endoftext|>


<commit_before>'use strict';

var async = require('async');
var fmt   = require('util').format;
var knex  = require('knex');
var pg    = require('pg');

pg.on('end', function onPgEnd() {
  LivePg.willClose = true;
});

/**
 * Get a livedb client for connecting to a PostgreSQL database.
 *
 * @classdesc A PostgreSQL adapter for livedb
 * @class
 * @param {string} conn a PostgreSQL connection URL
 * @param {string} table a database table name
 */
function LivePg(conn, table) {
  this.conn  = conn;
  this.db    = knex({ client: 'pg', connection: conn });
  this.table = table;
}

/*
 * SNAPSHOT API
 * ============
 */

/**
 * A callback called when getting a document snapshot.
 *
 * @callback LivePg~getSnapshotCallback
 * @param {?Error} err an error
 * @param {?Object} doc document data
 */
/**
 * Get a document snapshot from a given collection.
 *
 * @method
 * @param {string} cName the collection name
 * @param {string} docName the document name
 * @param {LivePg~getSnapshotCallback} cb a callback called with the document
 */
LivePg.prototype.getSnapshot = function getSnapshot(cName, docName, cb) {
  this.db(this.table)
    .where({ collection: cName, name: docName })
    .select('data')
    .limit(1)
    .exec(function onResult(err, rows) {
      if (err) return cb(err, null);
      cb(null, rows.length ? rows[0].data : null);
    });
};

/**
 * A callback called when writing a document snapshot.
 *
 * @callback LivePg~writeSnapshotCallback
 * @param {?Error} err an error
 * @param {?Object} doc document data
 */
/**
 * Write a document snapshot to a given collection.
 *
 * This method uses pg instead of knex because of the complex transaction and
 * locking that's necessary. The lock prevents a race condition between a failed
 * `UPDATE` and the subsequent `INSERT`.
 *
 * @method
 * @param {string} cName the collection name
 * @param {string} docName the document name
 * @param {Object} data the document data
 * @param {LivePg~writeSnapshotCallback} cb a callback called with the document
 */
LivePg.prototype.writeSnapshot = function writeSnapshot(cName, docName, data, cb) {
  var conn  = this.conn;
  var table = this.table;
  var client, done;

  async.waterfall([
    connect,
    begin,
    lock,
    upsert,
    commit
  ], function onDone(err) {
    if (done) done();
    if (err) return cb(err);
    cb(null, data);
  });

  function connect(callback) {
    pg.connect(conn, callback);
  }

  function begin(_client, _done, callback) {
    client = _client;
    done   = _done;
    client.query('BEGIN;', callback);
  }

  function lock(res, callback) {
    var _table = client.escapeIdentifier(table);
    var query  = fmt('LOCK TABLE %s IN SHARE ROW EXCLUSIVE MODE;', _table);
    client.query(query, callback);
  }

  function upsert(res, callback) {
    var _table   = client.escapeIdentifier(table);

    var update = fmt('UPDATE %s SET data = $1 ' +
      'WHERE collection = $2 AND name = $3', _table);

    var insert = fmt('INSERT INTO %s (collection, name, data) ' +
      'SELECT $2, $3, $1', _table);

    var query = fmt('WITH upsert AS (%s RETURNING *) %s ' +
      'WHERE NOT EXISTS (SELECT * FROM upsert);', update, insert);

    client.query(query, [data, cName, docName], callback);
  }

  function commit(res, callback) {
    client.query('COMMIT;', callback);
  }
};

/**
 * A callback called when getting snapshots in bulk.
 *
 * @callback LivePg~bulkGetSnapshotCallback
 * @param {?Error} err an error
 * @param {?Object} results the results
 */
/**
 * Get specific documents from multiple collections.
 *
 * @method
 * @param {Object} requests the requests documents
 * @param {LivePg~bulkGetSnapshotCallback} cb a callback called with the results
 */
LivePg.prototype.bulkGetSnapshot = function bulkGetSnapshot(requests, cb) {
  var collections = Object.keys(requests);

  async.parallel(collections.map(function eachCollection(cName) {
    var docNames = requests[cName];

    return function getFromCollection(callback) {
      this.fromCollection(cName, docNames, callback);
    }.bind(this);
  }.bind(this)), function onDone(err, results) {
    if (err) return cb(err);
    cb(null, results.reduce(function eachResult(obj, result, i) {
      obj[collections[i]] = result;
      return obj;
    }, {}));
  });
};

/**
 * A callback called when getting snapshots for a given collection.
 *
 * @callback LivePg~fromCollectionCallback
 * @private
 * @param {?Error} err an error
 * @param {?Object} results an set of results for the found documents
 */
/**
 * Get specific documents from a given collection.
 *
 * @method
 * @private
 * @param {string} cName the collection name
 * @param {Array} docNames the document names
 * @param {LivePg~fromCollectionCallback} cb a callback called with results
 */
LivePg.prototype.fromCollection = function fromCollection(cName, docNames, cb) {
  this.db(this.table)
    .whereIn('name', docNames)
    .andWhere({ collection: cName })
    .select('name', 'data')
    .exec(function onResult(err, results) {
      if (err) return cb(err, null);
      cb(null, results.reduce(function eachResult(obj, result) {
        obj[result.name] = result.data;
        return obj;
      }, {}));
    });
};

/*
 * OPERATION API
 * =============
 */

/**
 * A callback called when writing an operation
 *
 * @callback LivePg~writeOpCallback
 * @param {?Error} err an error
 * @param {?Object} op the operation data
 */
/**
 * Write an operation.
 *
 * @method
 * @param {string} cName a collection name
 * @param {string} docName a document name
 * @param {Object} opData the operation data
 * @param {LivePg~writeOpCallback} cb a callback called with the op data
 */
LivePg.prototype.writeOp = function writeOp(cName, docName, opData, cb) {
  this.db(this.table)
    .insert({
      collection_name: cName,
      document_name  : docName,
      version        : opData.v,
      data           : opData
    })
    .returning('data')
    .exec(function onResult(err, rows) {
      if (err) return cb(err, null);
      cb(null, rows.length ? rows[0] : null);
    });
};

/**
 * A callback called with the next version of the document
 *
 * @callback LivePg~getVersionCallback
 * @param {?Error} err an error
 * @param {?number} version the next document version
 */
/**
 * Get the next document version.
 *
 * @method
 * @param {string} cName a collection name
 * @param {string} docName a document name
 * @param {LivePg~getVersionCallback} cb a callback called with the next version
 */
LivePg.prototype.getVersion = function getVersion(cName, docName, cb) {
  this.db(this.table)
    .where({ collection_name: cName, document_name: docName })
    .select('version')
    .orderBy('version', 'desc')
    .limit(1)
    .exec(function onResult(err, rows) {
      if (err) return cb(err);
      cb(null, rows.length ? parseInt(rows[0].version, 10) + 1 : 0);
    });
};

/**
 * A callback called with ops
 *
 * @callback LivePg~getOpsCallback
 * @param {?Error} err an error
 * @param {?Array(Object)} ops the requested ops
 */
/**
 * Get operations between `start` and `end`, noninclusively.
 *
 * @method
 * @param {string} cName a collection name
 * @param {string} docName a document name
 * @param {number} start the start version
 * @param {?end} end the end version
 * @param {LivePg~getOpsCallback} cb a callback called with the ops
 */
LivePg.prototype.getOps = function getOps(cName, docName, start, end, cb) {
  var query = this.db(this.table)
    .where('version', '>=', start)
    .andWhere({ collection_name: cName, document_name: docName });

  if (typeof end === 'number') {
    query.andWhere('version', '<', end);
  }

  query.select('data')
    .orderBy('version', 'asc')
    .exec(function onResult(err, rows) {
      if (err) return cb(err);
      cb(null, rows.map(function eachRow(row) {
        return row.data;
      }));
    });
};

/**
 * Close the connection to the database.
 *
 * @method
 * @param {LivePg~closeCallback} cb a callback called when the connection closes
 */
LivePg.prototype.close = function close(cb) {
  LivePg.close(cb);
};

/**
 * A callback called when the database connection has closed
 *
 * @callback LivePg~closeCallback
 * @static
 */
/**
 * Close the connection to the database.
 *
 * @method
 * @static
 * @param {LivePg~closeCallback} cb a callback called when the connection closes
 */
LivePg.close = function close(cb) {
  if (this.willClose) {
    cb();
  } else {
    pg.on('end', function onPgEnd() {
      cb();
    });

    pg.end();
  }
};

module.exports = LivePg;
<commit_msg>Clean up callbacks<commit_after>'use strict';

var async = require('async');
var fmt   = require('util').format;
var knex  = require('knex');
var pg    = require('pg');

pg.on('end', function onPgEnd() {
  LivePg.willClose = true;
});

/**
 * Get a livedb client for connecting to a PostgreSQL database.
 *
 * @classdesc A PostgreSQL adapter for livedb
 * @class
 * @param {string} conn a PostgreSQL connection URL
 * @param {string} table a database table name
 */
function LivePg(conn, table) {
  this.conn  = conn;
  this.db    = knex({ client: 'pg', connection: conn });
  this.table = table;
}

/*
 * SNAPSHOT API
 * ============
 */

/**
 * A callback called when getting a document snapshot.
 *
 * @callback LivePg~getSnapshotCallback
 * @param {?Error} err an error
 * @param {?Object} doc document data
 */
/**
 * Get a document snapshot from a given collection.
 *
 * @method
 * @param {string} cName the collection name
 * @param {string} docName the document name
 * @param {LivePg~getSnapshotCallback} cb a callback called with the document
 */
LivePg.prototype.getSnapshot = function getSnapshot(cName, docName, cb) {
  this.db(this.table)
    .where({ collection: cName, name: docName })
    .select('data')
    .limit(1)
    .exec(function onResult(err, rows) {
      if (err) return cb(err, null);
      cb(null, rows.length ? rows[0].data : null);
    });
};

/**
 * A callback called when writing a document snapshot.
 *
 * @callback LivePg~writeSnapshotCallback
 * @param {?Error} err an error
 * @param {?Object} doc document data
 */
/**
 * Write a document snapshot to a given collection.
 *
 * This method uses pg instead of knex because of the complex transaction and
 * locking that's necessary. The lock prevents a race condition between a failed
 * `UPDATE` and the subsequent `INSERT`.
 *
 * @method
 * @param {string} cName the collection name
 * @param {string} docName the document name
 * @param {Object} data the document data
 * @param {LivePg~writeSnapshotCallback} cb a callback called with the document
 */
LivePg.prototype.writeSnapshot = function writeSnapshot(cName, docName, data, cb) {
  var conn  = this.conn;
  var table = this.table;
  var client, done;

  async.waterfall([
    connect,
    begin,
    lock,
    upsert,
    commit
  ], function onDone(err) {
    if (done) done();
    if (err) return cb(err, null);
    cb(null, data);
  });

  function connect(callback) {
    pg.connect(conn, callback);
  }

  function begin(_client, _done, callback) {
    client = _client;
    done   = _done;
    client.query('BEGIN;', callback);
  }

  function lock(res, callback) {
    var _table = client.escapeIdentifier(table);
    var query  = fmt('LOCK TABLE %s IN SHARE ROW EXCLUSIVE MODE;', _table);
    client.query(query, callback);
  }

  function upsert(res, callback) {
    var _table = client.escapeIdentifier(table);

    var update = fmt('UPDATE %s SET data = $1 ' +
      'WHERE collection = $2 AND name = $3', _table);

    var insert = fmt('INSERT INTO %s (collection, name, data) ' +
      'SELECT $2, $3, $1', _table);

    var query = fmt('WITH upsert AS (%s RETURNING *) %s ' +
      'WHERE NOT EXISTS (SELECT * FROM upsert);', update, insert);

    client.query(query, [data, cName, docName], callback);
  }

  function commit(res, callback) {
    client.query('COMMIT;', callback);
  }
};

/**
 * A callback called when getting snapshots in bulk.
 *
 * @callback LivePg~bulkGetSnapshotCallback
 * @param {?Error} err an error
 * @param {?Object} results the results
 */
/**
 * Get specific documents from multiple collections.
 *
 * @method
 * @param {Object} requests the requests documents
 * @param {LivePg~bulkGetSnapshotCallback} cb a callback called with the results
 */
LivePg.prototype.bulkGetSnapshot = function bulkGetSnapshot(requests, cb) {
  var collections = Object.keys(requests);

  async.parallel(collections.map(function eachCollection(cName) {
    var docNames = requests[cName];

    return function getFromCollection(callback) {
      this.fromCollection(cName, docNames, callback);
    }.bind(this);
  }.bind(this)), function onDone(err, results) {
    if (err) return cb(err);
    cb(null, results.reduce(function eachResult(obj, result, i) {
      obj[collections[i]] = result;
      return obj;
    }, {}));
  });
};

/**
 * A callback called when getting snapshots for a given collection.
 *
 * @callback LivePg~fromCollectionCallback
 * @private
 * @param {?Error} err an error
 * @param {?Object} results an set of results for the found documents
 */
/**
 * Get specific documents from a given collection.
 *
 * @method
 * @private
 * @param {string} cName the collection name
 * @param {Array} docNames the document names
 * @param {LivePg~fromCollectionCallback} cb a callback called with results
 */
LivePg.prototype.fromCollection = function fromCollection(cName, docNames, cb) {
  this.db(this.table)
    .whereIn('name', docNames)
    .andWhere({ collection: cName })
    .select('name', 'data')
    .exec(function onResult(err, results) {
      if (err) return cb(err, null);
      cb(null, results.reduce(function eachResult(obj, result) {
        obj[result.name] = result.data;
        return obj;
      }, {}));
    });
};

/*
 * OPERATION API
 * =============
 */

/**
 * A callback called when writing an operation
 *
 * @callback LivePg~writeOpCallback
 * @param {?Error} err an error
 * @param {?Object} op the operation data
 */
/**
 * Write an operation.
 *
 * @method
 * @param {string} cName a collection name
 * @param {string} docName a document name
 * @param {Object} opData the operation data
 * @param {LivePg~writeOpCallback} cb a callback called with the op data
 */
LivePg.prototype.writeOp = function writeOp(cName, docName, opData, cb) {
  this.db(this.table)
    .insert({
      collection_name: cName,
      document_name  : docName,
      version        : opData.v,
      data           : opData
    })
    .returning('data')
    .exec(function onResult(err, rows) {
      if (err) return cb(err, null);
      cb(null, rows[0]);
    });
};

/**
 * A callback called with the next version of the document
 *
 * @callback LivePg~getVersionCallback
 * @param {?Error} err an error
 * @param {?number} version the next document version
 */
/**
 * Get the next document version.
 *
 * @method
 * @param {string} cName a collection name
 * @param {string} docName a document name
 * @param {LivePg~getVersionCallback} cb a callback called with the next version
 */
LivePg.prototype.getVersion = function getVersion(cName, docName, cb) {
  this.db(this.table)
    .where({ collection_name: cName, document_name: docName })
    .select('version')
    .orderBy('version', 'desc')
    .limit(1)
    .exec(function onResult(err, rows) {
      if (err) return cb(err, null);
      cb(null, rows.length ? parseInt(rows[0].version, 10) + 1 : 0);
    });
};

/**
 * A callback called with ops
 *
 * @callback LivePg~getOpsCallback
 * @param {?Error} err an error
 * @param {?Array(Object)} ops the requested ops
 */
/**
 * Get operations between `start` and `end`, noninclusively.
 *
 * @method
 * @param {string} cName a collection name
 * @param {string} docName a document name
 * @param {number} start the start version
 * @param {?end} end the end version
 * @param {LivePg~getOpsCallback} cb a callback called with the ops
 */
LivePg.prototype.getOps = function getOps(cName, docName, start, end, cb) {
  var query = this.db(this.table)
    .where('version', '>=', start)
    .andWhere({ collection_name: cName, document_name: docName });

  if (typeof end === 'number') {
    query.andWhere('version', '<', end);
  }

  query.select('data')
    .orderBy('version', 'asc')
    .exec(function onResult(err, rows) {
      if (err) return cb(err, null);
      cb(null, rows.map(function eachRow(row) {
        return row.data;
      }));
    });
};

/**
 * Close the connection to the database.
 *
 * @method
 * @param {LivePg~closeCallback} cb a callback called when the connection closes
 */
LivePg.prototype.close = function close(cb) {
  LivePg.close(cb);
};

/**
 * A callback called when the database connection has closed
 *
 * @callback LivePg~closeCallback
 * @static
 */
/**
 * Close the connection to the database.
 *
 * @method
 * @static
 * @param {LivePg~closeCallback} cb a callback called when the connection closes
 */
LivePg.close = function close(cb) {
  if (this.willClose) {
    cb();
  } else {
    pg.on('end', function onPgEnd() {
      cb();
    });

    pg.end();
  }
};

module.exports = LivePg;
<|endoftext|>