<commit_before>/* SBHS-Timetable-Node: Countdown and timetable all at once (NodeJS app).
 * Copyright (C) 2014 James Ye, Simon Shields
 *
 * This file is part of SBHS-Timetable-Node.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/* global belltimes, todayNames, currentBellIndex, calculateUpcomingLesson, updatePeriodLabel, updateSidebarStatus */ /* jshint -W098 */

function handleLeftPane() {
	/* Fill out the left pane */
	'use strict';
	var pane = document.getElementById('left-pane'),
		html = '

Subject	Teacher	Room
',
		timetable = todayNames.timetable,
		prefix, subj, suffix, room, teacher, fullTeacher, subjName, final,
		roomChanged, teacherChanged, cancelled = false;
	if (window.timetableCached) {
		html = '
This data may be outdated
' + html;
	}
	for (var i = 1; i < 6; i++) {
		if (!(i in timetable) || !timetable[i].room) {
			html += '
Free
';
		}
		else {
			todayNames.timetable[i].expanded = false;
			prefix = '';
			subj = '';
			suffix = '';
			subj = timetable[i].title;
			room = timetable[i].room;
			teacher = timetable[i].teacher;
			fullTeacher = timetable[i].fullTeacher;
			subjName = timetable[i].fullName;
			final = timetable.variationsFinalised;
			if (/\d$/.test(timetable[i].title) || /[a-z][A-Z]$/.test(timetable[i].title)) {
				suffix = timetable[i].title.substr(-1);
				subj = subj.slice(0,-1);
			}
			if (subj.length == 3 /*|| (subj.length == 2 && suffix === '')*/ || /^[WXYZ]/.test(subj)) { // very tentative guess that this is an elective - char 1 should be prefix
				prefix = subj[0];
				subj = subj.substr(1);
			}
			if (timetable[i].changed) {
				if (timetable[i].hasOwnProperty('hasCover') && timetable[i].varies) { // don't show anything because I really don't get what the point of setting a casual but then not actually using aforementioned casual is.
					if (!timetable[i].hasCover) {
						cancelled = true;
					}
					else if (timetable[i].hasCasual) {
						teacherChanged = true;
						teacher = timetable[i].casual.toUpperCase();
						fullTeacher = timetable[i].casualDisplay.trim();
					}
				}
				if (timetable[i].roomFrom) {
					roomChanged = true;
					room = timetable[i].roomTo;
				}
			}
			var nSubj = '';
			var idx = 0;

			for (var j = 0; j < subj.length; j++) {
				var z = subjName.indexOf(subj[j+1]);
				z = z < 0 ? undefined : z;
				var mStr = subjName.substring(idx+1, z);
				nSubj += subj[j] + ''+mStr+'';
				idx = z;
			}
			var nTeach = '';
			idx = 0;
			var temp = teacher.toLowerCase();
			var fullTemp = fullTeacher;
			if (/^M(r|s) /.test(fullTemp)) {
				fullTemp = fullTemp.split(' ').slice(1).join(' ');
			}
			for (var k = 0; k < teacher.length; k++) {
				var y = fullTemp.toLowerCase().indexOf(temp[k+1]);
				y = y < 0 ? undefined : y;
				var extra = fullTemp.substring(idx+1, y);
				nTeach += teacher[k].toLowerCase() + ''+extra.toLowerCase()+'';
				idx = y;
			}
			html += '
'+timetable[i].year+prefix+''+nSubj+''+suffix+'	'+nTeach+'	'+room+'
';
			cancelled = false;
			roomChanged = false;
			teacherChanged = false;
		}
	}
	html += '

';
	if (todayNames.variationsFinalised) {
		html += 'This info is final
';
	}
	else {
		html += 'This info may change
';
	}
	pane.innerHTML = html;

}

function getLoggedIn() {
	/* Are you logged in? */
	'use strict';
	return window.loggedIn;
}

function expandSubject(event, id) {
	'use strict';
	if (todayNames.timetable[id].expanded) {
		$('.subj-expand', event.toElement.parentElement).velocity('transition.slideLeftBigOut');
		todayNames.timetable[id].expanded = false;
	}
	else {
		$('.subj-expand', event.toElement.parentElement).velocity('transition.slideLeftBigIn');
		todayNames.timetable[id].expanded = true;
	}

}

function teacherExpand(event, id) {
	'use strict';
	if (todayNames.timetable[id].teachExpanded) {
		$('.teach-expand', event.toElement.parentElement).velocity('transition.slideLeftBigOut');
		todayNames.timetable[id].teachExpanded = false;
	}
	else {
		$('.teach-expand', event.toElement.parentElement).velocity('transition.slideLeftBigIn');
		todayNames.timetable[id].teachExpanded = true;
	}
}

function handleTimetable() {
	/* Fill out the timetable */
	'use strict';
	/* jshint validthis: true */
	window.timetableCached = false;
	var lsKey = belltimes.day + belltimes.weekType;
	var res = JSON.parse(this.responseText);
	if (res.timetable && !res.hasVariations) {
		window.localStorage[lsKey] = this.responseText;
	}
	else if (!res.timetable) {
		$('#rtd-status').html('Real-time data inaccessible');
		return; // we don't want to do that... TODO refresh access token and stuff
	}
	window.todayNames = res;
	$('#rtd-status').html('Loaded real-time data');
	setTimeout(function() {
		$('#rtd-status').velocity('fadeOut');
		setTimeout(function() { $('#rtd-status').velocity('fadeOut').html('').css({'display': 'block'}); }, 1000);
	}, 3000);
	if (currentBellIndex == -1) {
		calculateUpcomingLesson();
	}
	handleLeftPane();
	updatePeriodLabel();
	updateSidebarStatus();
}

function loadTimetable() {
	/* Get the timetable */
	'use strict';
	window.timetableCached = false;
	if ((belltimes.day+belltimes.weekType) in window.localStorage) {
		window.timetableCached = true;
		console.log('loading from localStorage');
		window.todayNames = JSON.parse(window.localStorage[belltimes.day+belltimes.weekType]);
		setTimeout(handleLeftPane, 0);
		updateSidebarStatus();
		$('#rtd-status').html('Loading real-time data…');
	}
	else if (!getLoggedIn() && !window.todayNames) {
		console.log('umm');
		window.todayNames = {timetable: {failure: true}};
	}
	if (!getLoggedIn()) {
		$('#rtd-status').html('Log in for real-time data');
		return;
	}
	var xhr = new XMLHttpRequest();
	xhr.onload = handleTimetable;
	xhr.open('GET', '/api/today.json?stupid_proxy_caching_is_stupid', true);
	xhr.send();
}
<commit_msg>Style tweaks, fake a short teacher when it makes no sense.<commit_after>/* SBHS-Timetable-Node: Countdown and timetable all at once (NodeJS app).
 * Copyright (C) 2014 James Ye, Simon Shields
 *
 * This file is part of SBHS-Timetable-Node.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/* global belltimes, todayNames, currentBellIndex, calculateUpcomingLesson, updatePeriodLabel, updateSidebarStatus */ /* jshint -W098 */

function handleLeftPane() {
	/* Fill out the left pane */
	'use strict';
	var pane = document.getElementById('left-pane'),
		html = '

Subject	Teacher	Room
',
		timetable = todayNames.timetable,
		prefix, subj, suffix, room, teacher, fullTeacher, subjName, final,
		roomChanged, teacherChanged, cancelled = false;
	if (window.timetableCached) {
		html = '
This data may be outdated
' + html;
	}
	for (var i = 1; i < 6; i++) {
		if (!(i in timetable) || !timetable[i].room) {
			html += '
Free
';
		}
		else {
			todayNames.timetable[i].expanded = false;
			prefix = '';
			subj = '';
			suffix = '';
			subj = timetable[i].title;
			room = timetable[i].room;
			teacher = timetable[i].teacher;
			fullTeacher = timetable[i].fullTeacher;
			subjName = timetable[i].fullName;
			final = timetable.variationsFinalised;
			if (/\d$/.test(timetable[i].title) || /[a-z][A-Z]$/.test(timetable[i].title)) {
				suffix = timetable[i].title.substr(-1);
				subj = subj.slice(0,-1);
			}
			if (subj.length == 3 /*|| (subj.length == 2 && suffix === '')*/ || /^[WXYZ]/.test(subj)) { // very tentative guess that this is an elective - char 1 should be prefix
				prefix = subj[0];
				subj = subj.substr(1);
			}
			if (timetable[i].changed) {
				if (timetable[i].hasOwnProperty('hasCover') && timetable[i].varies) { // don't show anything because I really don't get what the point of setting a casual but then not actually using aforementioned casual is.
					if (!timetable[i].hasCover) {
						cancelled = true;
					}
					else if (timetable[i].hasCasual) {
						teacherChanged = true;
						teacher = timetable[i].casual.toUpperCase();
						fullTeacher = timetable[i].casualDisplay.trim();
					}
				}
				if (timetable[i].roomFrom) {
					roomChanged = true;
					room = timetable[i].roomTo;
				}
			}
			var nSubj = '';
			var idx = 0;

			for (var j = 0; j < subj.length; j++) {
				var z = subjName.indexOf(subj[j+1]);
				z = z < 0 ? undefined : z;
				var mStr = subjName.substring(idx+1, z);
				nSubj += subj[j] + ''+mStr+'';
				idx = z;
			}
			var nTeach = '';
			idx = 0;
			var temp = teacher.toLowerCase();
			var fullTemp = fullTeacher;
			if (/^M(r|s) /.test(fullTemp)) {
				fullTemp = fullTemp.split(' ').slice(1).join(' ');
			}
			if (fullTemp[0].toLowerCase() !== teacher[0].toLowerCase()) {
				// we'll make up a prefix - probably a split class
				teacher = temp = fullTemp[0] + fullTemp.substr(-1);
				temp = temp.toLowerCase();
			}
			for (var k = 0; k < teacher.length; k++) {
				var y = fullTemp.toLowerCase().indexOf(temp[k+1]);
				y = y < 0 ? undefined : y;
				var extra = fullTemp.substring(idx+1, y);
				nTeach += teacher[k].toUpperCase() + ''+extra.toLowerCase()+'';
				idx = y;
			}
			html += '
'+timetable[i].year+prefix+''+nSubj+''+suffix+'	'+nTeach+'	'+room+'
';
			cancelled = false;
			roomChanged = false;
			teacherChanged = false;
		}
	}
	html += '

';
	if (todayNames.variationsFinalised) {
		html += 'This info is final
';
	}
	else {
		html += 'This info may change
';
	}
	pane.innerHTML = html;

}

function getLoggedIn() {
	/* Are you logged in? */
	'use strict';
	return window.loggedIn;
}

function expandSubject(event, id) {
	'use strict';
	if (todayNames.timetable[id].expanded) {
		$('.subj-expand', event.toElement.parentElement).velocity('transition.slideLeftBigOut');
		todayNames.timetable[id].expanded = false;
	}
	else {
		$('.subj-expand', event.toElement.parentElement).velocity('transition.slideLeftBigIn');
		todayNames.timetable[id].expanded = true;
	}

}

function teacherExpand(event, id) {
	'use strict';
	if (todayNames.timetable[id].teachExpanded) {
		$('.teach-expand', event.toElement.parentElement).velocity('transition.slideLeftBigOut');
		todayNames.timetable[id].teachExpanded = false;
	}
	else {
		$('.teach-expand', event.toElement.parentElement).velocity('transition.slideLeftBigIn');
		todayNames.timetable[id].teachExpanded = true;
	}
}

function handleTimetable() {
	/* Fill out the timetable */
	'use strict';
	/* jshint validthis: true */
	window.timetableCached = false;
	var lsKey = belltimes.day + belltimes.weekType;
	var res = JSON.parse(this.responseText);
	if (res.timetable && !res.hasVariations) {
		window.localStorage[lsKey] = this.responseText;
	}
	else if (!res.timetable) {
		$('#rtd-status').html('Real-time data inaccessible');
		return; // we don't want to do that... TODO refresh access token and stuff
	}
	window.todayNames = res;
	$('#rtd-status').html('Loaded real-time data');
	setTimeout(function() {
		$('#rtd-status').velocity('fadeOut');
		setTimeout(function() { $('#rtd-status').velocity('fadeOut').html('').css({'display': 'block'}); }, 1000);
	}, 3000);
	if (currentBellIndex == -1) {
		calculateUpcomingLesson();
	}
	handleLeftPane();
	updatePeriodLabel();
	updateSidebarStatus();
}

function loadTimetable() {
	/* Get the timetable */
	'use strict';
	window.timetableCached = false;
	if ((belltimes.day+belltimes.weekType) in window.localStorage) {
		window.timetableCached = true;
		console.log('loading from localStorage');
		window.todayNames = JSON.parse(window.localStorage[belltimes.day+belltimes.weekType]);
		setTimeout(handleLeftPane, 0);
		updateSidebarStatus();
		$('#rtd-status').html('Loading real-time data…');
	}
	else if (!getLoggedIn() && !window.todayNames) {
		console.log('umm');
		window.todayNames = {timetable: {failure: true}};
	}
	if (!getLoggedIn()) {
		$('#rtd-status').html('Log in for real-time data');
		return;
	}
	var xhr = new XMLHttpRequest();
	xhr.onload = handleTimetable;
	xhr.open('GET', '/api/today.json?stupid_proxy_caching_is_stupid', true);
	xhr.send();
}
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash/fp');
const path = require('path');
const express = require('express');
const gutil = require('gulp-util');
const webpack = require('webpack');
const {exists} = require('../utils');
const webpackConfig = require('../../config/webpack.config.client');
const projectConfig = require('../../config/project');
const webpackMiddleware = require('webpack-dev-middleware');

const compiler = options => {
  gutil.log(`Bundling with Webpack (${options.debug ? 'debug' : 'release'})`);

  const configurations = [webpackConfig]
    .map(config => config(options))
    .filter(hasEntries);

  return webpack(configurations);
};

const runWebpack = options => {
  return new Promise((resolve, reject) => {
    compiler(options).run((err, stats) => {
      if (err || stats.hasErrors()) {
        gutil.log(gutil.colors.red(stats.toJson({}, true).errors.join('\n')));
        return reject(err);
      } else {
        return resolve();
      }
    });
  });
};

function getCorsMiddleware() {
  return (req, res, next) => {
    res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
    res.setHeader('Access-Control-Allow-Origin', '*');
    next();
  };
}

function getWebpackDevMiddleware(bundler) {
  try {
    return webpackMiddleware(bundler, {
      noInfo: true,
      stats: {
        colors: true
      }
    });
  } catch (e) {
    return (req, res, next) => next();
  }
}

function startWebpack({hot}) {
  const port = projectConfig.servers.cdn.port();
  const clientFilesPath = projectConfig.clientFilesPath();
  const bundler = compiler({debug: true, hot});
  const app = express().use(getCorsMiddleware());
  if (bundler) {
    app.use(getWebpackDevMiddleware(bundler));
    if (hot) {
      app.use(require('webpack-hot-middleware')(bundler));
    }
  }
  app.use(express.static(clientFilesPath)).listen(port, 'localhost');
}

function hasEntriesWithExtensions(extensions) {
  return entry => {
    return extensions
      .map(ext => `${entry}.${ext}`).concat(entry)
      .some(exists);
  };
}

function hasEntries(webpackConfig) {
  const entries = webpackConfig.entry;
  const context = webpackConfig.context;

  return _(entries)
    .values()
    .map(entry => _.isArray(entry) ? entry : [entry])
    .every(
      modules => _(modules)
        .map(module => path.join(context, module))
        .some(hasEntriesWithExtensions(['js', 'ts', 'tsx']))
  );
}

module.exports = {
  startWebpack,
  runWebpack
};
<commit_msg>improve(node-build): cleanup webpack output<commit_after>'use strict';

const _ = require('lodash/fp');
const path = require('path');
const express = require('express');
const gutil = require('gulp-util');
const webpack = require('webpack');
const {exists} = require('../utils');
const webpackConfig = require('../../config/webpack.config.client');
const projectConfig = require('../../config/project');
const webpackMiddleware = require('webpack-dev-middleware');

const compiler = ({debug}) => {
  gutil.log(`Bundling with Webpack (${debug ? 'debug' : 'release'})`);

  const config = [webpackConfig]
    .map(config => config({debug}))
    .filter(hasEntries)
    .shift() || [];

  return filterNoise(webpack(config));
};

const runWebpack = options => {
  return new Promise((resolve, reject) => {
    compiler(options).run((err, stats) => {
      if (err || stats.hasErrors()) {
        // gutil.log(gutil.colors.red(stats.toJson({}, true).errors.join('\n')));
        return reject(err);
      } else {
        return resolve();
      }
    });
  });
};

function getCorsMiddleware() {
  return (req, res, next) => {
    res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
    res.setHeader('Access-Control-Allow-Origin', '*');
    next();
  };
}

function getWebpackDevMiddleware(bundler) {
  try {
    return webpackMiddleware(bundler, {
      noInfo: true,
      stats: {
        colors: true
      }
    });
  } catch (e) {
    return (req, res, next) => next();
  }
}

function startWebpack({hot}) {
  const port = projectConfig.servers.cdn.port();
  const clientFilesPath = projectConfig.clientFilesPath();
  const bundler = compiler({debug: true, hot});
  const app = express().use(getCorsMiddleware());
  if (bundler) {
    app.use(getWebpackDevMiddleware(bundler));
    if (hot) {
      app.use(require('webpack-hot-middleware')(bundler));
    }
  }
  app.use(express.static(clientFilesPath)).listen(port, 'localhost');
}

function hasEntriesWithExtensions(extensions) {
  return entry => {
    return extensions
      .map(ext => `${entry}.${ext}`).concat(entry)
      .some(exists);
  };
}

function hasEntries(webpackConfig) {
  const entries = webpackConfig.entry;
  const context = webpackConfig.context;

  return _(entries)
    .values()
    .map(entry => _.isArray(entry) ? entry : [entry])
    .every(
      modules => _(modules)
        .map(module => path.join(context, module))
        .some(hasEntriesWithExtensions(['js', 'ts', 'tsx']))
  );
}

function filterNoise(comp) {
  comp.plugin('done', stats => {
    // Hack to remove extract-text-webpack-plugin messages
    // https://github.com/webpack/extract-text-webpack-plugin/issues/35
    // const messages = stats.stats || [];
    // messages.forEach(stat => {
    //   stat.compilation.children = stat.compilation.children.filter(child =>
    //     child.name !== 'extract-text-webpack-plugin');
    // });

    gutil.log(stats.toString({
      colors: true,
      hash: false,
      chunks: false,
      assets: false,
      children: false
    }));
  });

  return comp;
}

module.exports = {
  startWebpack,
  runWebpack
};
<|endoftext|>


<commit_before>var Tessel = require('./tessel');
var commands = require('./commands');
var logs = require('../logs');
var fs = require('fs');
var path = require('path');
var tar = require('tar');
var Ignore = require('fstream-ignore');

var RUN_PATH = '/tmp/remote-script/';
var PUSH_PATH = '/app/';
var PUSH_START_SCRIPT_NAME = 'start';
var NODE_PUSH_SCRIPT = __dirname + '/../../resources/start_node_script.sh';

// Used to store local functionality and allow
// exporting those definitions for testing.
var actions = {};

/*
  Run a script on a Tessel
    param opts: unused so far
*/
Tessel.prototype.deployScript = function(opts) {
  var self = this;
  // Only an _explicit_ `true` will set push mode
  var isPush = opts.push === true;

  return new Promise(function(resolve, reject) {
    var filepath = isPush ? PUSH_PATH : RUN_PATH;

    // Stop running any existing scripts
    return actions.execRemoteCommand(self, 'stopRunningScript', filepath)
      .then(pushBundle(filepath))
      .then(function(script) {
        if (isPush) {
          // Push the script into flash
          actions.pushScript(self, script).then(resolve);
        } else {
          // Push the code into ram
          actions.runScript(self, filepath, script).then(resolve);
        }
      })
      .catch(reject);
  });

  function pushBundle(filepath) {
    return function pushBundlePromise() {
      return new Promise(function(resolve) {
        var prom = Promise.resolve();

        if (opts.single) {
          // Always be sure the appropriate dir is created
          prom.then(actions.execRemoteCommand(self, 'createFolder', filepath));
        } else {
          // Delete any code that was previously at this file path
          prom.then(actions.execRemoteCommand(self, 'deleteFolder', filepath)
            // Create the folder again
            .then(actions.execRemoteCommand(self, 'createFolder', filepath)));
        }

        // Bundle and send tarred code to T2
        prom.then(resolve(actions.sendBundle(self, filepath, opts)));
      });
    };
  };
};

Tessel.prototype.restartScript = function(opts) {
  var self = this;
  var isPush = opts.type === 'flash';
  var filepath = isPush ? PUSH_PATH : RUN_PATH;

  return new Promise(function(resolve, reject) {
    return self.connection.exec(commands.readFile(filepath + opts.entryPoint))
      .then(function(remoteProcess) {
        var error = '';

        remoteProcess.stderr.on('data', function(data) {
          error += data.toString();
        });

        remoteProcess.once('close', function() {
          if (error.length) {
            if (error.indexOf('No such file or directory') !== -1) {
              error = '"' + opts.entryPoint + '" not found on ' + self.name;
            }

            return reject(error);
          } else {
            if (isPush) {
              // Start the script from flash memory
              actions.startPushedScript(self, opts.entryPoint)
                .then(resolve).catch(reject);
            } else {
              // Start the script in RAM
              actions.runScript(self, filepath, opts.entryPoint)
                .then(resolve).catch(reject);
            }
          }
        });
      });
  });
};

actions.execRemoteCommand = function(tessel, command, filepath) {
  return new Promise(function(resolve) {
    return tessel.connection.exec(commands[command](filepath))
      .then(function(remoteProcess) {
        remoteProcess.once('close', resolve);
      });
  });
};

actions.findProject = function(file) {
  return new Promise(function(resolve, reject) {
    var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
    var checkPkgJson = false;
    var isDirectory = false;

    // Addresses an encountered edge case where
    // paths wouldn't resolve correctly:
    //
    // > fs.realpathSync("~/foo");
    // Error: ENOENT, no such file or directory '/Users/me/foo/~'
    // > path.dirname("~/foo")
    // '~'
    // > path.resolve("~/foo")
    // '/Users/me/foo/~/foo'
    //
    //  ...And so on...
    //
    if (/^~/.test(file)) {
      file = file.replace(/^~/, home);
    }

    try {
      // This will throw if the file or directory doesn't
      // exist. The cost of the try/catch is negligible.
      isDirectory = fs.lstatSync(file).isDirectory();
    } catch (error) {
      reject(error.message);
    }

    if (isDirectory) {
      file = path.join(file, 'index.js');
      checkPkgJson = true;
    }

    var pushdir = fs.realpathSync(path.dirname(file));
    var relpath = '';

    while (path.dirname(pushdir) !== pushdir &&
      !fs.existsSync(path.join(pushdir, 'package.json'))) {
      relpath = path.join(path.basename(pushdir), relpath);
      pushdir = path.dirname(pushdir);
    }

    if (path.dirname(pushdir) === pushdir) {
      reject('Invalid project directory');
    }

    var program = path.join(pushdir, relpath, path.basename(file));
    var pkgJson = '';
    var basename = '';

    if (checkPkgJson) {
      pkgJson = require(path.join(pushdir, 'package.json'));

      if (pkgJson.main) {
        basename = path.basename(program);
        program = path.normalize(program.replace(basename, pkgJson.main));
      }
    }

    resolve({
      pushdir: pushdir,
      program: program,
      entryPoint: path.join(relpath, path.basename(program)),
    });
  });
};

actions.sendBundle = function(t, filepath, opts) {
  return new Promise(function(resolve, reject) {
    // Execute the remote untar process command
    return t.connection.exec(commands.untarStdin(filepath))
      // Once the process starts running
      .then(function(remoteProcess) {
        var error = '';

        actions.findProject(opts.entryPoint).then(function(project) {
          var resolved = path.resolve(process.cwd(), project.pushdir);

          // Collect error data as received
          remoteProcess.stderr.on('data', function(data) {
            error += data.toString();
          });

          actions.tarBundle(resolved).then(function(bundle) {
            if (error) {
              return reject(error);
            }

            // RAM or Flash for log
            var memtype;
            if (opts.push) {
              memtype = 'Flash';
            } else {
              memtype = 'RAM';
            }

            // Log write
            logs.info('Writing %s to %s on %s (%d kB)...', project.entryPoint, memtype, t.name, bundle.length / 1000);

            // Wait for the transfer to finish...
            remoteProcess.once('close', function() {
              logs.info('Deployed.');
              resolve(project.entryPoint);
            });

            // Write the code bundle to the hardware
            remoteProcess.stdin.end(bundle);
          });

        }).catch(reject);
      });
  });
};

actions.tarBundle = function(target) {
  var cwd = target || process.cwd();
  return new Promise(function(resolve, reject) {
    var buffers = [];
    var pack = tar.Pack();
    var fstream = new Ignore({
      path: cwd,
      ignoreFiles: ['.tesselignore']
    });

    fstream.basename = '';
    pack._noProprietary = true;

    // This ensures that the remote root directory
    // is the same level as the directory containing
    // our program entry-point files.
    fstream.on('entry', function(entry) {
      entry.root = {
        path: entry.path
      };
    });

    // Send the ignore-filtered file stream into the tar packer
    fstream.pipe(pack)
      .on('data', function(chunk) {
        buffers.push(chunk);
      })
      .on('error', function(data) {
        reject(data);
      })
      .on('end', function() {
        resolve(Buffer.concat(buffers));
      });
  });
};

actions.runScript = function(t, filepath, entryPoint) {
  logs.info('Running %s...', entryPoint);
  return new Promise(function(resolve) {
    return t.connection.exec(commands.runScript(filepath, entryPoint))
      .then(function(remoteProcess) {
        function scriptStopped() {
          logs.info('Stopping script...');
          resolve();
        }

        // Once we get a SIGINT from the console, stop the script
        process.once('SIGINT', scriptStopped);

        // When the stream closes
        remoteProcess.once('close', function removeListener() {
          // Remove the process listener
          process.removeListener('SIGINT', scriptStopped);
          // Report the stopped script and quit
          scriptStopped();
        });

        // Pipe data and errors
        remoteProcess.stdout.pipe(process.stdout);
        remoteProcess.stderr.pipe(process.stderr);
      });
  });
};

actions.pushScript = function(t, entryPoint) {
  // Write the node start file
  return actions.writeToFile(t)
    .then(function start() {
      // Then start the script
      return actions.startPushedScript(t, entryPoint);
    });
};

actions.writeToFile = function(t) {
  return new Promise(function(resolve, reject) {
    // Path of the script to run a Node project
    var executablePath = PUSH_PATH + PUSH_START_SCRIPT_NAME;
    // Open a stdin pipe tp the file
    return t.connection.exec(commands.openStdinToFile(executablePath))
      // If it was opened successfully
      .then(function(remoteProcess) {
        // When the remote process finishes
        remoteProcess.stdin.once('finish', function() {
          // Set the perimissions on the file to be executable
          return t.connection.exec(commands.setExecutablePermissions(executablePath))
            .then(function(remoteProcess) {
              // When that process completes
              remoteProcess.once('close', function() {
                // Let the user know
                logs.info('You may now disconnect from the Tessel. Your code will be run whenever Tessel boots up. To remove this code, use `tessel erase`.');
                return resolve();
              });
            });
        });

        // Read the contents of the node start script
        fs.readFile(NODE_PUSH_SCRIPT, function(err, data) {
          if (err) {
            return reject(err);
          }
          // Write the Node start script
          remoteProcess.stdin.end(data);
        });
      });
  });
};

actions.startPushedScript = function(t, entryPoint) {
  return new Promise(function(resolve) {
    // Once it has been written, run the script with Node
    return t.connection.exec(commands.startPushedScript())
      .then(function(remoteProcess) {
        remoteProcess.once('close', function() {
          logs.info('Running %s...', entryPoint);
          return resolve();
        });
      });
  });
};

if (global.IS_TEST_ENV) {
  module.exports = actions;
}
<commit_msg>clean up promises<commit_after>var Tessel = require('./tessel');
var commands = require('./commands');
var logs = require('../logs');
var fs = require('fs');
var path = require('path');
var tar = require('tar');
var Ignore = require('fstream-ignore');

var RUN_PATH = '/tmp/remote-script/';
var PUSH_PATH = '/app/';
var PUSH_START_SCRIPT_NAME = 'start';
var NODE_PUSH_SCRIPT = __dirname + '/../../resources/start_node_script.sh';

// Used to store local functionality and allow
// exporting those definitions for testing.
var actions = {};

/*
  Run a script on a Tessel
    param opts: unused so far
*/
Tessel.prototype.deployScript = function(opts) {
  var self = this;
  // Only an _explicit_ `true` will set push mode
  var isPush = opts.push === true;

  return new Promise(function(resolve, reject) {
    var filepath = isPush ? PUSH_PATH : RUN_PATH;

    // Stop running any existing scripts
    return actions.execRemoteCommand(self, 'stopRunningScript', filepath)
      .then(function() {
        var prom;

        if (opts.single) {
          // Always be sure the appropriate dir is created
          prom = actions.execRemoteCommand(self, 'createFolder', filepath);
        } else {
          // Delete any code that was previously at this file path
          prom = actions.execRemoteCommand(self, 'deleteFolder', filepath);
          // Create the folder again
          prom.then(function() {
            return actions.execRemoteCommand(self, 'createFolder', filepath);
          });
        }

        // Bundle and send tarred code to T2
        return prom.then(function() {
          return actions.sendBundle(self, filepath, opts);
        })
          .then(function(script) {
            if (isPush) {
              // Push the script into flash
              return actions.pushScript(self, script).then(resolve);
            } else {
              // Push the code into ram
              return actions.runScript(self, filepath, script).then(resolve);
            }
          });
      })
      .catch(reject);
  });
};

Tessel.prototype.restartScript = function(opts) {
  var self = this;
  var isPush = opts.type === 'flash';
  var filepath = isPush ? PUSH_PATH : RUN_PATH;

  return new Promise(function(resolve, reject) {
    return self.connection.exec(commands.readFile(filepath + opts.entryPoint))
      .then(function(remoteProcess) {
        var error = '';

        remoteProcess.stderr.on('data', function(data) {
          error += data.toString();
        });

        remoteProcess.once('close', function() {
          if (error.length) {
            if (error.indexOf('No such file or directory') !== -1) {
              error = '"' + opts.entryPoint + '" not found on ' + self.name;
            }

            return reject(error);
          } else {
            if (isPush) {
              // Start the script from flash memory
              actions.startPushedScript(self, opts.entryPoint)
                .then(resolve).catch(reject);
            } else {
              // Start the script in RAM
              actions.runScript(self, filepath, opts.entryPoint)
                .then(resolve).catch(reject);
            }
          }
        });
      });
  });
};

actions.execRemoteCommand = function(tessel, command, filepath) {
  return new Promise(function(resolve) {
    return tessel.connection.exec(commands[command](filepath))
      .then(function(remoteProcess) {
        remoteProcess.once('close', resolve);
      });
  });
};

actions.findProject = function(file) {
  return new Promise(function(resolve, reject) {
    var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
    var checkPkgJson = false;
    var isDirectory = false;

    // Addresses an encountered edge case where
    // paths wouldn't resolve correctly:
    //
    // > fs.realpathSync("~/foo");
    // Error: ENOENT, no such file or directory '/Users/me/foo/~'
    // > path.dirname("~/foo")
    // '~'
    // > path.resolve("~/foo")
    // '/Users/me/foo/~/foo'
    //
    //  ...And so on...
    //
    if (/^~/.test(file)) {
      file = file.replace(/^~/, home);
    }

    try {
      // This will throw if the file or directory doesn't
      // exist. The cost of the try/catch is negligible.
      isDirectory = fs.lstatSync(file).isDirectory();
    } catch (error) {
      reject(error.message);
    }

    if (isDirectory) {
      file = path.join(file, 'index.js');
      checkPkgJson = true;
    }

    var pushdir = fs.realpathSync(path.dirname(file));
    var relpath = '';

    while (path.dirname(pushdir) !== pushdir &&
      !fs.existsSync(path.join(pushdir, 'package.json'))) {
      relpath = path.join(path.basename(pushdir), relpath);
      pushdir = path.dirname(pushdir);
    }

    if (path.dirname(pushdir) === pushdir) {
      reject('Invalid project directory');
    }

    var program = path.join(pushdir, relpath, path.basename(file));
    var pkgJson = '';
    var basename = '';

    if (checkPkgJson) {
      pkgJson = require(path.join(pushdir, 'package.json'));

      if (pkgJson.main) {
        basename = path.basename(program);
        program = path.normalize(program.replace(basename, pkgJson.main));
      }
    }

    resolve({
      pushdir: pushdir,
      program: program,
      entryPoint: path.join(relpath, path.basename(program)),
    });
  });
};

actions.sendBundle = function(t, filepath, opts) {
  return new Promise(function(resolve, reject) {
    // Execute the remote untar process command
    return t.connection.exec(commands.untarStdin(filepath))
      // Once the process starts running
      .then(function(remoteProcess) {
        var error = '';

        actions.findProject(opts.entryPoint).then(function(project) {
          var resolved = path.resolve(process.cwd(), project.pushdir);

          // Collect error data as received
          remoteProcess.stderr.on('data', function(data) {
            error += data.toString();
          });

          actions.tarBundle(resolved).then(function(bundle) {
            if (error) {
              return reject(error);
            }

            // RAM or Flash for log
            var memtype;
            if (opts.push) {
              memtype = 'Flash';
            } else {
              memtype = 'RAM';
            }

            // Log write
            logs.info('Writing %s to %s on %s (%d kB)...', project.entryPoint, memtype, t.name, bundle.length / 1000);

            // Wait for the transfer to finish...
            remoteProcess.once('close', function() {
              logs.info('Deployed.');
              resolve(project.entryPoint);
            });

            // Write the code bundle to the hardware
            remoteProcess.stdin.end(bundle);
          });

        }).catch(reject);
      });
  });
};

actions.tarBundle = function(target) {
  var cwd = target || process.cwd();
  return new Promise(function(resolve, reject) {
    var buffers = [];
    var pack = tar.Pack();
    var fstream = new Ignore({
      path: cwd,
      ignoreFiles: ['.tesselignore']
    });

    fstream.basename = '';
    pack._noProprietary = true;

    // This ensures that the remote root directory
    // is the same level as the directory containing
    // our program entry-point files.
    fstream.on('entry', function(entry) {
      entry.root = {
        path: entry.path
      };
    });

    // Send the ignore-filtered file stream into the tar packer
    fstream.pipe(pack)
      .on('data', function(chunk) {
        buffers.push(chunk);
      })
      .on('error', function(data) {
        reject(data);
      })
      .on('end', function() {
        resolve(Buffer.concat(buffers));
      });
  });
};

actions.runScript = function(t, filepath, entryPoint) {
  logs.info('Running %s...', entryPoint);
  return new Promise(function(resolve) {
    return t.connection.exec(commands.runScript(filepath, entryPoint))
      .then(function(remoteProcess) {
        function scriptStopped() {
          logs.info('Stopping script...');
          resolve();
        }

        // Once we get a SIGINT from the console, stop the script
        process.once('SIGINT', scriptStopped);

        // When the stream closes
        remoteProcess.once('close', function removeListener() {
          // Remove the process listener
          process.removeListener('SIGINT', scriptStopped);
          // Report the stopped script and quit
          scriptStopped();
        });

        // Pipe data and errors
        remoteProcess.stdout.pipe(process.stdout);
        remoteProcess.stderr.pipe(process.stderr);
      });
  });
};

actions.pushScript = function(t, entryPoint) {
  // Write the node start file
  return actions.writeToFile(t)
    .then(function start() {
      // Then start the script
      return actions.startPushedScript(t, entryPoint);
    });
};

actions.writeToFile = function(t) {
  return new Promise(function(resolve, reject) {
    // Path of the script to run a Node project
    var executablePath = PUSH_PATH + PUSH_START_SCRIPT_NAME;
    // Open a stdin pipe tp the file
    return t.connection.exec(commands.openStdinToFile(executablePath))
      // If it was opened successfully
      .then(function(remoteProcess) {
        // When the remote process finishes
        remoteProcess.stdin.once('finish', function() {
          // Set the perimissions on the file to be executable
          return t.connection.exec(commands.setExecutablePermissions(executablePath))
            .then(function(remoteProcess) {
              // When that process completes
              remoteProcess.once('close', function() {
                // Let the user know
                logs.info('You may now disconnect from the Tessel. Your code will be run whenever Tessel boots up. To remove this code, use `tessel erase`.');
                return resolve();
              });
            });
        });

        // Read the contents of the node start script
        fs.readFile(NODE_PUSH_SCRIPT, function(err, data) {
          if (err) {
            return reject(err);
          }
          // Write the Node start script
          remoteProcess.stdin.end(data);
        });
      });
  });
};

actions.startPushedScript = function(t, entryPoint) {
  return new Promise(function(resolve) {
    // Once it has been written, run the script with Node
    return t.connection.exec(commands.startPushedScript())
      .then(function(remoteProcess) {
        remoteProcess.once('close', function() {
          logs.info('Running %s...', entryPoint);
          return resolve();
        });
      });
  });
};

if (global.IS_TEST_ENV) {
  module.exports = actions;
}
<|endoftext|>


<commit_before>import { Job as KueJob } from 'kue'

export class Job {
	static jobName = null
	static priority = 'normal'
	static removeOnComplete = true
	static attempts = 1
	static backoff = null
	static concurrency = 1

	$kueJob = null
	$queue = null

	constructor(data = { }, $kueJob = null) {
		Object.assign(this, data)
		this.$kueJob = $kueJob || (() => {
			const job = new KueJob
			job.attempts(this.constructor.attempts)
			job.priority(this.constructor.priority)
			job.removeOnComplete(this.constructor.removeOnComplete)
			job.backoff(this.constructor.backoff)
			job.events(false)
			return job
		})()
	}

	get id() {
		return this.$kueJob.id
	}

	// eslint-disable-next-line no-unused-vars
	$handle(app, queue) {
		//
	}

	$priority(...args) {
		this.$kueJob.priority(...args)
		return this
	}

	$delay(...args) {
		this.$kueJob.delay(...args)
		return this
	}

	$attempts(...args) {
		this.$kueJob.attempts(...args)
		return this
	}

	$backoff(...args) {
		this.$kueJob.backoff(...args)
		return this
	}

	$ttl(...args) {
		this.$kueJob.ttl(...args)
		return this
	}

	$progress(...args) {
		this.$kueJob.progress(...args)
		return this
	}

	$log(...args) {
		this.$kueJob.log(...args)
		return this
	}

	$save(queue) {
		if(this.id.isNil) {
			if(queue.isNil) {
				throw new Error('Calling $save on new jobs requires a queue parameter.')
			}

			const jobName = this.constructor.jobName

			if(jobName.isNil) {
				throw new Error('Invalid Job, must have `jobName` set.')
			}

			if(queue.jobs[jobName].isNil) {
				throw new Error('This job is not yet registered with the target queue.')
			}

			this.$kueJob.type = jobName
			this.$kueJob.client = queue.kue.client
		}

		this.$kueJob.data = this.toJSON()

		return new Promise((resolve, reject) => {
			let resolved = false

			this.$kueJob.save(err => {
				if(resolved) {
					return
				}

				resolved = true

				if(!err.isNil) {
					return reject(err)
				}

				resolved = true
				return resolve(this)
			})
		})
	}

	toJSON() {
		return this.$toJson()
	}

	$toJson() {
		const json = Object.assign({ }, this)

		for(const key of Object.keys(json)) {
			if(key.substring(0, 1) !== '$') {
				continue
			}

			delete json[key]
		}

		return json
	}

}
<commit_msg>add isDelayedFor function<commit_after>import { Job as KueJob } from 'kue'

export class Job {
	static jobName = null
	static priority = 'normal'
	static removeOnComplete = true
	static attempts = 1
	static backoff = null
	static concurrency = 1

	$kueJob = null
	$queue = null

	constructor(data = { }, $kueJob = null) {
		Object.assign(this, data)
		this.$kueJob = $kueJob || (() => {
			const job = new KueJob
			job.attempts(this.constructor.attempts)
			job.priority(this.constructor.priority)
			job.removeOnComplete(this.constructor.removeOnComplete)
			job.backoff(this.constructor.backoff)
			job.events(false)
			return job
		})()
	}

	get id() {
		return this.$kueJob.id
	}

	// eslint-disable-next-line no-unused-vars
	$handle(app, queue) {
		//
	}

	$priority(...args) {
		this.$kueJob.priority(...args)
		return this
	}

	$delay(...args) {
		this.$kueJob.delay(...args)
		return this
	}

	$isDelayedFor(ms) {
		return (this.$kueJob.promote_at - Date.now()) > ms
	}

	$attempts(...args) {
		this.$kueJob.attempts(...args)
		return this
	}

	$backoff(...args) {
		this.$kueJob.backoff(...args)
		return this
	}

	$ttl(...args) {
		this.$kueJob.ttl(...args)
		return this
	}

	$progress(...args) {
		this.$kueJob.progress(...args)
		return this
	}

	$log(...args) {
		this.$kueJob.log(...args)
		return this
	}

	$save(queue) {
		if(this.id.isNil) {
			if(queue.isNil) {
				throw new Error('Calling $save on new jobs requires a queue parameter.')
			}

			const jobName = this.constructor.jobName

			if(jobName.isNil) {
				throw new Error('Invalid Job, must have `jobName` set.')
			}

			if(queue.jobs[jobName].isNil) {
				throw new Error('This job is not yet registered with the target queue.')
			}

			this.$kueJob.type = jobName
			this.$kueJob.client = queue.kue.client
		}

		this.$kueJob.data = this.toJSON()

		return new Promise((resolve, reject) => {
			let resolved = false

			this.$kueJob.save(err => {
				if(resolved) {
					return
				}

				resolved = true

				if(!err.isNil) {
					return reject(err)
				}

				resolved = true
				return resolve(this)
			})
		})
	}

	toJSON() {
		return this.$toJson()
	}

	$toJson() {
		const json = Object.assign({ }, this)

		for(const key of Object.keys(json)) {
			if(key.substring(0, 1) !== '$') {
				continue
			}

			delete json[key]
		}

		return json
	}

}
<|endoftext|>


<commit_before>function pwtCreatePrebidNamespace(namespace) {
	window[namespace] = window[namespace] || {}; window[namespace].que = window[namespace].que || [];
<commit_msg>a minor change in variable name<commit_after>function pwtCreatePrebidNamespace(preBidNameSpace) {
	window[preBidNameSpace] = window[preBidNameSpace] || {}; window[preBidNameSpace].que = window[preBidNameSpace].que || [];
<|endoftext|>


<commit_before>'use strict';

var hasOwnProperty = Object.prototype.hasOwnProperty;
var noop = function() {};

function ensureFunction(value) {
    return typeof value === 'function' ? value : noop;
}

function invokeForType(fn, type) {
    return function(node, item, list) {
        if (node.type === type) {
            fn.call(this, node, item, list);
        }
    };
}

function getWalkersFromStructure(name, nodeType) {
    var structure = nodeType.structure;
    var walkers = [];

    for (var key in structure) {
        if (hasOwnProperty.call(structure, key) === false) {
            continue;
        }

        var fieldTypes = structure[key];
        var walker = {
            name: key,
            type: false,
            nullable: false
        };

        if (!Array.isArray(structure[key])) {
            fieldTypes = [structure[key]];
        }

        for (var i = 0; i < fieldTypes.length; i++) {
            var fieldType = fieldTypes[i];
            if (fieldType === null) {
                walker.nullable = true;
            } else if (typeof fieldType === 'string') {
                walker.type = 'node';
            } else if (Array.isArray(fieldType)) {
                walker.type = 'list';
            }
        }

        if (walker.type) {
            walkers.push(walker);
        }
    }

    if (walkers.length) {
        return {
            context: nodeType.walkContext,
            fields: walkers
        };
    }

    return null;
}

function getTypesFromConfig(config) {
    var types = {};

    if (config.node) {
        for (var name in config.node) {
            if (hasOwnProperty.call(config.node, name)) {
                var nodeType = config.node[name];

                if (nodeType.structure) {
                    var walkers = getWalkersFromStructure(name, nodeType);
                    if (walkers !== null) {
                        types[name] = walkers;
                    }
                } else {
                    throw new Error('Missed `structure` field in `' + name + '` node type definition');
                }
            }
        }
    }

    return types;
}

function createHandler(config, reverse) {
    return new Function('node', 'context', 'walk',
        (config.context ? 'var old = context.' + config.context + ';\ncontext.' + config.context + ' = node;\n' : '') +
        config.fields.map(function(field) {
            var ref = 'node.' + field.name;
            var line;

            if (field.type === 'list') {
                if (reverse) {
                    line = [
                        'if (Array.isArray(' + ref + ')) {',
                            'for (var i = ' + ref + '.length - 1; i >= 0; i++) {',
                                'walk(' + ref + '[i], i, ' + ref + ')',
                            '}',
                        '} else {',
                            ref + '.forEachRight(walk);',
                        '}'
                    ].join('');
                } else {
                    line = ref + '.forEach(walk);';
                }
            } else {
                line = 'walk(' + ref + ');';
            }

            if (field.nullable) {
                line = 'if (' + ref + ') {\n    ' + line + '}';
            }

            return line;
        }).join('\n') +
        (config.context ? '\ncontext.' + config.context + ' = old;' : '')
    );
}

function createVisitHandlers(handlers) {
    return {
        Atrule: {
            StyleSheet: handlers.StyleSheet,
            Atrule: handlers.Atrule,
            Rule: handlers.Rule,
            Block: handlers.Block
        },
        Rule: {
            StyleSheet: handlers.StyleSheet,
            Atrule: handlers.Atrule,
            Rule: handlers.Rule,
            Block: handlers.Block
        },
        Declaration: {
            StyleSheet: handlers.StyleSheet,
            Atrule: handlers.Atrule,
            Rule: handlers.Rule,
            Block: handlers.Block
        }
    };
}

function createContext(root, fn) {
    var context = {
        fn: fn,
        root: root,
        stylesheet: null,
        atrule: null,
        atrulePrelude: null,
        rule: null,
        selector: null,
        block: null,
        declaration: null,
        function: null
    };

    return context;
}

module.exports = function createWalker(config) {
    var types = getTypesFromConfig(config);
    var handlers = {};
    var handlersReverse = {};

    for (var name in types) {
        if (hasOwnProperty.call(types, name)) {
            handlers[name] = createHandler(types[name], false);
            handlersReverse[name] = createHandler(types[name], true);
        }
    }

    var visitHandlers = createVisitHandlers(handlers);
    var visitHandlersReverse = createVisitHandlers(handlersReverse);

    return function walk(root, options) {
        function walkNode(node, item, list) {
            enter.call(context, node, item, list);

            if (contextHandlers.hasOwnProperty(node.type)) {
                contextHandlers[node.type](node, context, walkNode);
            }

            leave.call(context, node, item, list);
        }

        var enter = noop;
        var leave = noop;
        var contextHandlers = handlers;
        var context = createContext(root, null);

        if (typeof options === 'function') {
            enter = options;
        } else if (options) {
            enter = ensureFunction(options.enter);
            leave = ensureFunction(options.leave);

            if (options.visit) {
                if (visitHandlers.hasOwnProperty(options.visit)) {
                    contextHandlers = options.reverse
                        ? visitHandlersReverse[options.visit]
                        : visitHandlers[options.visit];
                    enter = invokeForType(enter, options.visit);
                    leave = invokeForType(leave, options.visit);
                } else {
                    throw new Error('Bad value for `visit` option (should be one of ' + Object.keys(visitHandlers).join(', ') + ')');
                }
            } else if (options.reverse) {
                contextHandlers = handlersReverse;
            }
        }

        if (enter === noop && leave === noop) {
            throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
        }

        walkNode(root);
    };
};
<commit_msg>internal refactoring<commit_after>'use strict';

var hasOwnProperty = Object.prototype.hasOwnProperty;
var noop = function() {};

function ensureFunction(value) {
    return typeof value === 'function' ? value : noop;
}

function invokeForType(fn, type) {
    return function(node, item, list) {
        if (node.type === type) {
            fn.call(this, node, item, list);
        }
    };
}

function getWalkersFromStructure(name, nodeType) {
    var structure = nodeType.structure;
    var walkers = [];

    for (var key in structure) {
        if (hasOwnProperty.call(structure, key) === false) {
            continue;
        }

        var fieldTypes = structure[key];
        var walker = {
            name: key,
            type: false,
            nullable: false
        };

        if (!Array.isArray(structure[key])) {
            fieldTypes = [structure[key]];
        }

        for (var i = 0; i < fieldTypes.length; i++) {
            var fieldType = fieldTypes[i];
            if (fieldType === null) {
                walker.nullable = true;
            } else if (typeof fieldType === 'string') {
                walker.type = 'node';
            } else if (Array.isArray(fieldType)) {
                walker.type = 'list';
            }
        }

        if (walker.type) {
            walkers.push(walker);
        }
    }

    if (walkers.length) {
        return {
            context: nodeType.walkContext,
            fields: walkers
        };
    }

    return null;
}

function getTypesFromConfig(config) {
    var types = {};

    if (config.node) {
        for (var name in config.node) {
            if (hasOwnProperty.call(config.node, name)) {
                var nodeType = config.node[name];

                if (nodeType.structure) {
                    var walkers = getWalkersFromStructure(name, nodeType);
                    if (walkers !== null) {
                        types[name] = walkers;
                    }
                } else {
                    throw new Error('Missed `structure` field in `' + name + '` node type definition');
                }
            }
        }
    }

    return types;
}

function createHandler(config, reverse) {
    return new Function('node', 'context', 'walk',
        (config.context ? 'var old = context.' + config.context + ';\ncontext.' + config.context + ' = node;\n' : '') +
        config.fields.map(function(field) {
            var ref = 'node.' + field.name;
            var line;

            if (field.type === 'list') {
                if (reverse) {
                    line = [
                        'if (Array.isArray(' + ref + ')) {',
                            'for (var i = ' + ref + '.length - 1; i >= 0; i++) {',
                                'walk(' + ref + '[i], i, ' + ref + ')',
                            '}',
                        '} else {',
                            ref + '.forEachRight(walk);',
                        '}'
                    ].join('');
                } else {
                    line = ref + '.forEach(walk);';
                }
            } else {
                line = 'walk(' + ref + ');';
            }

            if (field.nullable) {
                line = 'if (' + ref + ') {\n    ' + line + '}';
            }

            return line;
        }).join('\n') +
        (config.context ? '\ncontext.' + config.context + ' = old;' : '')
    );
}

function createVisitHandlers(handlers) {
    return {
        Atrule: {
            StyleSheet: handlers.StyleSheet,
            Atrule: handlers.Atrule,
            Rule: handlers.Rule,
            Block: handlers.Block
        },
        Rule: {
            StyleSheet: handlers.StyleSheet,
            Atrule: handlers.Atrule,
            Rule: handlers.Rule,
            Block: handlers.Block
        },
        Declaration: {
            StyleSheet: handlers.StyleSheet,
            Atrule: handlers.Atrule,
            Rule: handlers.Rule,
            Block: handlers.Block
        }
    };
}

module.exports = function createWalker(config) {
    var types = getTypesFromConfig(config);
    var handlers = {};
    var handlersReverse = {};

    for (var name in types) {
        if (hasOwnProperty.call(types, name)) {
            handlers[name] = createHandler(types[name], false);
            handlersReverse[name] = createHandler(types[name], true);
        }
    }

    var visitHandlers = createVisitHandlers(handlers);
    var visitHandlersReverse = createVisitHandlers(handlersReverse);

    return function walk(root, options) {
        function walkNode(node, item, list) {
            enter.call(context, node, item, list);

            if (contextHandlers.hasOwnProperty(node.type)) {
                contextHandlers[node.type](node, context, walkNode);
            }

            leave.call(context, node, item, list);
        }

        var enter = noop;
        var leave = noop;
        var contextHandlers = handlers;
        var context = {
            root: root,
            stylesheet: null,
            atrule: null,
            atrulePrelude: null,
            rule: null,
            selector: null,
            block: null,
            declaration: null,
            function: null
        };

        if (typeof options === 'function') {
            enter = options;
        } else if (options) {
            enter = ensureFunction(options.enter);
            leave = ensureFunction(options.leave);

            if (options.visit) {
                if (visitHandlers.hasOwnProperty(options.visit)) {
                    contextHandlers = options.reverse
                        ? visitHandlersReverse[options.visit]
                        : visitHandlers[options.visit];
                    enter = invokeForType(enter, options.visit);
                    leave = invokeForType(leave, options.visit);
                } else {
                    throw new Error('Bad value for `visit` option (should be one of ' + Object.keys(visitHandlers).join(', ') + ')');
                }
            } else if (options.reverse) {
                contextHandlers = handlersReverse;
            }
        }

        if (enter === noop && leave === noop) {
            throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
        }

        walkNode(root);
    };
};
<|endoftext|>


<commit_before>var ConfigurationError = require("./configuration_error.js"),
    nsq = require("nsqjs"),
    Writable = require("stream").Writable,
    util = require("util");

var PART = {
    TOPIC: 0,
    MESSAGE: 1
};

function fieldGetter(field) {

    if (typeof field === "string") {
        return function (data) { return data[field]; };
    }

    if (typeof field === "function") {
        return field;
    }

    return function (data) { return data; };
}

/*jslint unparam:true*/
function getterWrite(chunk, encoding, callback) {
    var topic = this.getters.topic(chunk),
        message = this.getters.message(chunk);

    this.writer.publish(topic, message, function (error) {
        callback(error);
    });
}

function interleavedWrite(chunk, encoding, callback) {

    if (PART.TOPIC === this.part_type) {
        this.topic = this.getters.topic(chunk);
        callback();
    } else if (PART.MESSAGE === this.part_type) {
        this.writer.publish(this.topic, this.getters.message(chunk), function (error) {
            callback(error);
        });
    }

    this.part_type ^= 1; // Toggle type for next chunk.
}
/*jslint unparam:false*/

function WriterStream(nsqdHost, nsqdPort, options, getters) {

    if (!(this instanceof WriterStream)) {
        return new WriterStream(nsqdHost, nsqdPort, options);
    }

    Writable.call(this, { objectMode: true });

    var self = this;

    self.getters = {};
    if (getters) {
        self.getters.topic = fieldGetter(getters.topic);
        self.getters.message = fieldGetter(getters.message);
        self._write = getterWrite;
    } else if (options && options.hasOwnProperty("topic") && options.hasOwnProperty("message")) {
        self.getters.topic = fieldGetter(options.topic);
        self.getters.message = fieldGetter(options.message);
        self._write = getterWrite;
    } else {
        self.getters.topic = fieldGetter();
        self.getters.message = fieldGetter();
        self.part_type = 0;
        self._write = interleavedWrite;
    }

    self.writer = new nsq.Writer(nsqdHost, nsqdPort, options);
    self.writer.connect();

    self.writer.on("closed", function () {
        self.emit("close");
    });

    self.writer.on("error", function(error) {
        self.emit("error", error);
    });

    self.writer.on("ready", function () {
        self.emit("ready");
    });
}

util.inherits(WriterStream, Writable);

module.exports = WriterStream;

<commit_msg>Do not send getters to nsq.Writer client if options is missing.<commit_after>var ConfigurationError = require("./configuration_error.js"),
    nsq = require("nsqjs"),
    Writable = require("stream").Writable,
    util = require("util");

var PART = {
    TOPIC: 0,
    MESSAGE: 1
};

function fieldGetter(field) {

    if (typeof field === "string") {
        return function (data) { return data[field]; };
    }

    if (typeof field === "function") {
        return field;
    }

    return function (data) { return data; };
}

/*jslint unparam:true*/
function getterWrite(chunk, encoding, callback) {
    var topic = this.getters.topic(chunk),
        message = this.getters.message(chunk);

    this.writer.publish(topic, message, function (error) {
        callback(error);
    });
}

function interleavedWrite(chunk, encoding, callback) {

    if (PART.TOPIC === this.part_type) {
        this.topic = this.getters.topic(chunk);
        callback();
    } else if (PART.MESSAGE === this.part_type) {
        this.writer.publish(this.topic, this.getters.message(chunk), function (error) {
            callback(error);
        });
    }

    this.part_type ^= 1; // Toggle type for next chunk.
}
/*jslint unparam:false*/

function WriterStream(nsqdHost, nsqdPort, options, getters) {

    if (!(this instanceof WriterStream)) {
        return new WriterStream(nsqdHost, nsqdPort, options);
    }

    Writable.call(this, { objectMode: true });

    var self = this;

    if (options && options.hasOwnProperty("topic") && options.hasOwnProperty("message")) {
        getters = options;
        options = {};
    }

    self.getters = {};
    if (getters) {
        self.getters.topic = fieldGetter(getters.topic);
        self.getters.message = fieldGetter(getters.message);
        self._write = getterWrite;
    } else {
        self.getters.topic = fieldGetter();
        self.getters.message = fieldGetter();
        self.part_type = 0;
        self._write = interleavedWrite;
    }

    self.writer = new nsq.Writer(nsqdHost, nsqdPort, options);
    self.writer.connect();

    self.writer.on("closed", function () {
        self.emit("close");
    });

    self.writer.on("error", function(error) {
        self.emit("error", error);
    });

    self.writer.on("ready", function () {
        self.emit("ready");
    });
}

util.inherits(WriterStream, Writable);

module.exports = WriterStream;

<|endoftext|>


<commit_before>module.exports = {
	applicationName: 'lifxController',
	lifxApiAddress: 'https://api.lifx.com/v1/',
}
<commit_msg>Added default node-lifx client configs<commit_after>module.exports = {
	applicationName: 'lifxController',
	lifxApiAddress: 'https://api.lifx.com/v1/',
	nodeLifxClient: {
		messageHandlerTimeout: 2000,
		resendMaxTimes: 2,
	},
}
<|endoftext|>


<commit_before>$(document).ready(function() {
    Parse.initialize("VXRx5pZQAr263FPLmgqY2FHEa66zEOLIuK3I2rl6", "OQkMhfc7hMHcBBkiUoClnxAfrF8gpmKaC3jNKq5V");

    (function(d, s, id){
    var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = "http://connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
});

function logIn() {
    Parse.FacebookUtils.init({
        appId      : '789662264445561',
        cookie     : true,
        xfbml      : true,
        version    : 'v2.3'
    });

    Parse.FacebookUtils.logIn("user_friends", {
        success: function(user) {
            FB.api("/me", function(response) {
                user.set("name", response.name);
                user.set("facebook_id", response.id);
                user.save();
            });

            FB.api("/me/picture?type=large", function(response) {
                user.set("picture", response.data.url);
                user.save();
            });

            FB.api("/me/friends", function(response) {
                for (i = 0; i < response.data.length; i++) {
                    user.addUnique("friends", response.data[i].id);
                }

                user.save();
            });

            updateUserPage(user);
            retrieveSporklists(user);

            $("#login-box").fadeOut(700);
        },
        error: function(user, error) {
            alert("You must sign into Facebook to use this app");
        }
    });
};

function retrieveSporklists(user) {
    var sporklist = Parse.Object.extend("Sporklist");
    var query = new Parse.Query(sporklist);

    query.equalTo("author", user.getUsername());
    query.limit(1000);

    var lists = [];
    query.find({
        success: function(results) {
            // Do something with the returned Parse.Object values
            for (var i = 0; i < results.length; i++) {
                lists.push(results[i]);
            }

            updateSporklists(lists);
        },
        error: function(error) {
            alert("Error: " + error.code + " " + error.message);
        }
    });
}
<commit_msg>location<commit_after>$(document).ready(function() {
    Parse.initialize("VXRx5pZQAr263FPLmgqY2FHEa66zEOLIuK3I2rl6", "OQkMhfc7hMHcBBkiUoClnxAfrF8gpmKaC3jNKq5V");

    (function(d, s, id){
    var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = "http://connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
});

function logIn() {
    Parse.FacebookUtils.init({
        appId      : '789662264445561',
        cookie     : true,
        xfbml      : true,
        version    : 'v2.3'
    });

    Parse.FacebookUtils.logIn("user_friends", {
        success: function(user) {
            FB.api("/me", function(response) {
                user.set("name", response.name);
                user.set("facebook_id", response.id);
                user.save();
            });

            FB.api("/me/picture?type=large", function(response) {
                user.set("picture", response.data.url);
                user.save();
            });

            FB.api("/me/friends", function(response) {
                for (i = 0; i < response.data.length; i++) {
                    user.addUnique("friends", response.data[i].id);
                }

                user.save();
            });

            navigator.geolocation.getCurrentPosition(function(position) {
                console.log(position);
            });

            updateUserPage(user);
            retrieveSporklists(user);

            $("#login-box").fadeOut(700);
        },
        error: function(user, error) {
            alert("You must sign into Facebook to use this app");
        }
    });
};

function retrieveSporklists(user) {
    var sporklist = Parse.Object.extend("Sporklist");
    var query = new Parse.Query(sporklist);

    query.equalTo("author", user.getUsername());
    query.limit(1000);

    var lists = [];
    query.find({
        success: function(results) {
            // Do something with the returned Parse.Object values
            for (var i = 0; i < results.length; i++) {
                lists.push(results[i]);
            }

            updateSporklists(lists);
        },
        error: function(error) {
            alert("Error: " + error.code + " " + error.message);
        }
    });
}
<|endoftext|>


<commit_before>'use strict';

exports.up = function(knex) {
  return knex.schema.createTable('requests', (table) => {
    table.increments();
    table.integer('admin_id')
      .references('id')
      .inTable('users')
    table.integer('singer_id')
      .references('id')
      .inTable('users')
    table.integer('song_id')
      .references('id')
      .inTable('songs')
      .notNullable();
    table.string('artist_name');
    table.string('song_title')
    table.timestamps(true, true)
  })
};

exports.down = function(knex) {
  return knex.schema.dropTable('requests')
};
<commit_msg>Correct requests foreign keys<commit_after>'use strict';

exports.up = function(knex) {
  return knex.schema.createTable('requests', (table) => {
    table.increments();
    table.integer('admin_id')
      .notNullable()
      .references('id')
      .inTable('users')
      .onDelete('CASCADE')
      .index();
    table.integer('singer_id')
      .notNullable()
      .references('id')
      .inTable('users')
      .onDelete('CASCADE')
      .index();
    table.integer('song_id')
      .notNullable()
      .references('id')
      .inTable('songs')
      .onDelete('CASCADE')
      .index();
    table.string('artist_name');
    table.string('song_title');
    table.timestamps(true, true);
  })
};

exports.down = function(knex) {
  return knex.schema.dropTable('requests')
};
<|endoftext|>


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

const loaderUtils = require("loader-utils");

// copies the resources into the webapp directory.
//

// Languages are listed manually so we can choose when to include
// a translation in the app (because having a translation with only
// 3 strings translated is just frustrating)
// This could readily be automated, but it's nice to explicitly
// control when new languages are available.
const INCLUDE_LANGS = [
    {'value': 'bg', 'label': 'Български'},
    {'value': 'ca', 'label': 'Català'},
    {'value': 'cs', 'label': 'čeština'},
    {'value': 'da', 'label': 'Dansk'},
    {'value': 'de_DE', 'label': 'Deutsch'},
    {'value': 'el', 'label': 'Ελληνικά'},
    {'value': 'en_EN', 'label': 'English'},
    {'value': 'en_US', 'label': 'English (US)'},
    {'value': 'eo', 'label': 'Esperanto'},
    {'value': 'es', 'label': 'Español'},
    {'value': 'eu', 'label': 'Euskara'},
    {'value': 'fi', 'label': 'Suomi'},
    {'value': 'fr', 'label': 'Français'},
    {'value': 'gl', 'label': 'Galego'},
    {'value': 'hi', 'label': 'हिन्दी'},
    {'value': 'hu', 'label': 'Magyar'},
    {'value': 'is', 'label': 'íslenska'},
    {'value': 'it', 'label': 'Italiano'},
    {'value': 'ja', 'label': '日本語'},
    {'value': 'ko', 'label': '한국어'},
    {'value': 'lt', 'label': 'lietuvių kalba'},
    {'value': 'lv', 'label': 'Latviešu'},
    {'value': 'nb_NO', 'label': 'Norwegian Bokmål'},
    {'value': 'nl', 'label': 'Nederlands'},
    {'value': 'nn', 'label': 'Norsk Nynorsk'},
    {'value': 'pl', 'label': 'Polski'},
    {'value': 'pt', 'label': 'Português'},
    {'value': 'pt_BR', 'label': 'Português do Brasil'},
    {'value': 'ru', 'label': 'Русский'},
    {'value': 'sk', 'label': 'Slovenčina'},
    {'value': 'sq', 'label': 'Shqip'},
    {'value': 'sr', 'label': 'српски'},
    {'value': 'sv', 'label': 'Svenska'},
    {'value': 'te', 'label': 'తెలుగు'},
    {'value': 'th', 'label': 'ไทย'},
    {'value': 'tr', 'label': 'Türkçe'},
    {'value': 'uk', 'label': 'українська мова'},
    {'value': 'vls', 'label': 'West-Vlaams'},
    {'value': 'zh_Hans', 'label': '简体中文'}, // simplified chinese
    {'value': 'zh_Hant', 'label': '繁體中文'}, // traditional chinese
];

// cpx includes globbed parts of the filename in the destination, but excludes
// common parents. Hence, "res/{a,b}/**": the output will be "dest/a/..." and
// "dest/b/...".
const COPY_LIST = [
    ["res/manifest.json", "webapp"],
    ["res/welcome.html", "webapp"],
    ["res/welcome/**", "webapp/welcome"],
    ["res/themes/**", "webapp/themes"],
    ["res/vector-icons/**", "webapp/vector-icons"],
    ["node_modules/matrix-react-sdk/res/media/**", "webapp/media"],
    ["node_modules/olm/olm_legacy.js", "webapp", { directwatch: 1 }],
    ["./config.json", "webapp", { directwatch: 1 }],
];

const parseArgs = require('minimist');
const Cpx = require('cpx');
const chokidar = require('chokidar');
const fs = require('fs');
const rimraf = require('rimraf');

const argv = parseArgs(
    process.argv.slice(2), {}
);

const watch = argv.w;
const verbose = argv.v;

function errCheck(err) {
    if (err) {
        console.error(err.message);
        process.exit(1);
    }
}

// Check if webapp exists
if (!fs.existsSync('webapp')) {
    fs.mkdirSync('webapp');
}
// Check if i18n exists
if (!fs.existsSync('webapp/i18n/')) {
    fs.mkdirSync('webapp/i18n/');
}

function next(i, err) {
    errCheck(err);

    if (i >= COPY_LIST.length) {
        return;
    }

    const ent = COPY_LIST[i];
    const source = ent[0];
    const dest = ent[1];
    const opts = ent[2] || {};
    let cpx = undefined;

    if (!opts.lang) {
        cpx = new Cpx.Cpx(source, dest);
    }

    if (verbose && cpx) {
        cpx.on("copy", (event) => {
            console.log(`Copied: ${event.srcPath} --> ${event.dstPath}`);
        });
        cpx.on("remove", (event) => {
            console.log(`Removed: ${event.path}`);
        });
    }

    const cb = (err) => { next(i + 1, err) };

    if (watch) {
        if (opts.directwatch) {
            // cpx -w creates a watcher for the parent of any files specified,
            // which in the case of config.json is '.', which inevitably takes
            // ages to crawl. So we create our own watcher on the files
            // instead.
            const copy = () => { cpx.copy(errCheck) };
            chokidar.watch(source)
                .on('add', copy)
                .on('change', copy)
                .on('ready', cb)
                .on('error', errCheck);
        } else {
            cpx.on('watch-ready', cb);
            cpx.on("watch-error", cb);
            cpx.watch();
        }
    } else {
        cpx.copy(cb);
    }
}

function genLangFile(lang, dest) {
    const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + lang + '.json';
    const riotWebFile = 'src/i18n/strings/' + lang + '.json';

    let translations = {};
    [reactSdkFile, riotWebFile].forEach(function(f) {
        if (fs.existsSync(f)) {
            try {
                Object.assign(
                    translations,
                    JSON.parse(fs.readFileSync(f).toString())
                );
            } catch (e) {
                console.error("Failed: " + f, e);
                throw e;
            }
        }
    });

    translations = weblateToCounterpart(translations);

    const json = JSON.stringify(translations, null, 4);
    const jsonBuffer = Buffer.from(json);
    const digest = loaderUtils.getHashDigest(jsonBuffer, null, null, 7);
    const filename = `${lang}.${digest}.json`;

    fs.writeFileSync(dest + filename, json);
    if (verbose) {
        console.log("Generated language file: " + filename);
    }

    return filename;
}

function genLangList(langFileMap) {
    const languages = {};
    INCLUDE_LANGS.forEach(function(lang) {
        const normalizedLanguage = lang.value.toLowerCase().replace("_", "-");
        const languageParts = normalizedLanguage.split('-');
        if (languageParts.length == 2 && languageParts[0] == languageParts[1]) {
            languages[languageParts[0]] = {'fileName': langFileMap[lang.value], 'label': lang.label};
        } else {
            languages[normalizedLanguage] = {'fileName': langFileMap[lang.value], 'label': lang.label};
        }
    });
    fs.writeFile('webapp/i18n/languages.json', JSON.stringify(languages, null, 4), function(err) {
        if (err) {
            console.error("Copy Error occured: " + err);
            throw new Error("Failed to generate languages.json");
        }
    });
    if (verbose) {
        console.log("Generated languages.json");
    }
}

/**
 * Convert translation key from weblate format
 * (which only supports a single level) to counterpart
 * which requires object values for 'count' translations.
 *
 * eg.
 *     "there are %(count)s badgers|one": "a badger",
 *     "there are %(count)s badgers|other": "%(count)s badgers"
 *   becomes
 *     "there are %(count)s badgers": {
 *         "one": "a badger",
 *         "other": "%(count)s badgers"
 *     }
 */
function weblateToCounterpart(inTrs) {
    const outTrs = {};

    for (const key of Object.keys(inTrs)) {
        const keyParts = key.split('|', 2);
        if (keyParts.length === 2) {
            let obj = outTrs[keyParts[0]];
            if (obj === undefined) {
                obj = {};
                outTrs[keyParts[0]] = obj;
            }
            obj[keyParts[1]] = inTrs[key];
        } else {
            outTrs[key] = inTrs[key];
        }
    }

    return outTrs;
}

/**
watch the input files for a given language,
regenerate the file, adding its content-hashed filename to langFileMap
and regenerating languages.json with the new filename
*/
function watchLanguage(lang, dest, langFileMap) {
    const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + lang + '.json';
    const riotWebFile = 'src/i18n/strings/' + lang + '.json';

    // XXX: Use a debounce because for some reason if we read the language
    // file immediately after the FS event is received, the file contents
    // appears empty. Possibly https://github.com/nodejs/node/issues/6112
    let makeLangDebouncer;
    const makeLang = () => {
        if (makeLangDebouncer) {
            clearTimeout(makeLangDebouncer);
        }
        makeLangDebouncer = setTimeout(() => {
            const filename = genLangFile(lang, dest);
            langFileMap[lang]=filename;
            genLangList(langFileMap);
        }, 500);
    };

    [reactSdkFile, riotWebFile].forEach(function(f) {
        chokidar.watch(f)
            .on('add', makeLang)
            .on('change', makeLang)
            .on('error', errCheck);
    });
}

// language resources
const I18N_DEST = "webapp/i18n/";
const I18N_FILENAME_MAP = INCLUDE_LANGS.reduce((m, l) => {
    const filename = genLangFile(l.value, I18N_DEST);
    m[l.value] = filename;
    return m;
}, {});
genLangList(I18N_FILENAME_MAP);

if (watch) {
    INCLUDE_LANGS.forEach(l => watchLanguage(l.value, I18N_DEST, I18N_FILENAME_MAP));
}

// non-language resources
next(0);
<commit_msg>Update Lithuanian language name<commit_after>#!/usr/bin/env node

const loaderUtils = require("loader-utils");

// copies the resources into the webapp directory.
//

// Languages are listed manually so we can choose when to include
// a translation in the app (because having a translation with only
// 3 strings translated is just frustrating)
// This could readily be automated, but it's nice to explicitly
// control when new languages are available.
const INCLUDE_LANGS = [
    {'value': 'bg', 'label': 'Български'},
    {'value': 'ca', 'label': 'Català'},
    {'value': 'cs', 'label': 'čeština'},
    {'value': 'da', 'label': 'Dansk'},
    {'value': 'de_DE', 'label': 'Deutsch'},
    {'value': 'el', 'label': 'Ελληνικά'},
    {'value': 'en_EN', 'label': 'English'},
    {'value': 'en_US', 'label': 'English (US)'},
    {'value': 'eo', 'label': 'Esperanto'},
    {'value': 'es', 'label': 'Español'},
    {'value': 'eu', 'label': 'Euskara'},
    {'value': 'fi', 'label': 'Suomi'},
    {'value': 'fr', 'label': 'Français'},
    {'value': 'gl', 'label': 'Galego'},
    {'value': 'hi', 'label': 'हिन्दी'},
    {'value': 'hu', 'label': 'Magyar'},
    {'value': 'is', 'label': 'íslenska'},
    {'value': 'it', 'label': 'Italiano'},
    {'value': 'ja', 'label': '日本語'},
    {'value': 'ko', 'label': '한국어'},
    {'value': 'lt', 'label': 'Lietuvių'},
    {'value': 'lv', 'label': 'Latviešu'},
    {'value': 'nb_NO', 'label': 'Norwegian Bokmål'},
    {'value': 'nl', 'label': 'Nederlands'},
    {'value': 'nn', 'label': 'Norsk Nynorsk'},
    {'value': 'pl', 'label': 'Polski'},
    {'value': 'pt', 'label': 'Português'},
    {'value': 'pt_BR', 'label': 'Português do Brasil'},
    {'value': 'ru', 'label': 'Русский'},
    {'value': 'sk', 'label': 'Slovenčina'},
    {'value': 'sq', 'label': 'Shqip'},
    {'value': 'sr', 'label': 'српски'},
    {'value': 'sv', 'label': 'Svenska'},
    {'value': 'te', 'label': 'తెలుగు'},
    {'value': 'th', 'label': 'ไทย'},
    {'value': 'tr', 'label': 'Türkçe'},
    {'value': 'uk', 'label': 'українська мова'},
    {'value': 'vls', 'label': 'West-Vlaams'},
    {'value': 'zh_Hans', 'label': '简体中文'}, // simplified chinese
    {'value': 'zh_Hant', 'label': '繁體中文'}, // traditional chinese
];

// cpx includes globbed parts of the filename in the destination, but excludes
// common parents. Hence, "res/{a,b}/**": the output will be "dest/a/..." and
// "dest/b/...".
const COPY_LIST = [
    ["res/manifest.json", "webapp"],
    ["res/welcome.html", "webapp"],
    ["res/welcome/**", "webapp/welcome"],
    ["res/themes/**", "webapp/themes"],
    ["res/vector-icons/**", "webapp/vector-icons"],
    ["node_modules/matrix-react-sdk/res/media/**", "webapp/media"],
    ["node_modules/olm/olm_legacy.js", "webapp", { directwatch: 1 }],
    ["./config.json", "webapp", { directwatch: 1 }],
];

const parseArgs = require('minimist');
const Cpx = require('cpx');
const chokidar = require('chokidar');
const fs = require('fs');
const rimraf = require('rimraf');

const argv = parseArgs(
    process.argv.slice(2), {}
);

const watch = argv.w;
const verbose = argv.v;

function errCheck(err) {
    if (err) {
        console.error(err.message);
        process.exit(1);
    }
}

// Check if webapp exists
if (!fs.existsSync('webapp')) {
    fs.mkdirSync('webapp');
}
// Check if i18n exists
if (!fs.existsSync('webapp/i18n/')) {
    fs.mkdirSync('webapp/i18n/');
}

function next(i, err) {
    errCheck(err);

    if (i >= COPY_LIST.length) {
        return;
    }

    const ent = COPY_LIST[i];
    const source = ent[0];
    const dest = ent[1];
    const opts = ent[2] || {};
    let cpx = undefined;

    if (!opts.lang) {
        cpx = new Cpx.Cpx(source, dest);
    }

    if (verbose && cpx) {
        cpx.on("copy", (event) => {
            console.log(`Copied: ${event.srcPath} --> ${event.dstPath}`);
        });
        cpx.on("remove", (event) => {
            console.log(`Removed: ${event.path}`);
        });
    }

    const cb = (err) => { next(i + 1, err) };

    if (watch) {
        if (opts.directwatch) {
            // cpx -w creates a watcher for the parent of any files specified,
            // which in the case of config.json is '.', which inevitably takes
            // ages to crawl. So we create our own watcher on the files
            // instead.
            const copy = () => { cpx.copy(errCheck) };
            chokidar.watch(source)
                .on('add', copy)
                .on('change', copy)
                .on('ready', cb)
                .on('error', errCheck);
        } else {
            cpx.on('watch-ready', cb);
            cpx.on("watch-error", cb);
            cpx.watch();
        }
    } else {
        cpx.copy(cb);
    }
}

function genLangFile(lang, dest) {
    const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + lang + '.json';
    const riotWebFile = 'src/i18n/strings/' + lang + '.json';

    let translations = {};
    [reactSdkFile, riotWebFile].forEach(function(f) {
        if (fs.existsSync(f)) {
            try {
                Object.assign(
                    translations,
                    JSON.parse(fs.readFileSync(f).toString())
                );
            } catch (e) {
                console.error("Failed: " + f, e);
                throw e;
            }
        }
    });

    translations = weblateToCounterpart(translations);

    const json = JSON.stringify(translations, null, 4);
    const jsonBuffer = Buffer.from(json);
    const digest = loaderUtils.getHashDigest(jsonBuffer, null, null, 7);
    const filename = `${lang}.${digest}.json`;

    fs.writeFileSync(dest + filename, json);
    if (verbose) {
        console.log("Generated language file: " + filename);
    }

    return filename;
}

function genLangList(langFileMap) {
    const languages = {};
    INCLUDE_LANGS.forEach(function(lang) {
        const normalizedLanguage = lang.value.toLowerCase().replace("_", "-");
        const languageParts = normalizedLanguage.split('-');
        if (languageParts.length == 2 && languageParts[0] == languageParts[1]) {
            languages[languageParts[0]] = {'fileName': langFileMap[lang.value], 'label': lang.label};
        } else {
            languages[normalizedLanguage] = {'fileName': langFileMap[lang.value], 'label': lang.label};
        }
    });
    fs.writeFile('webapp/i18n/languages.json', JSON.stringify(languages, null, 4), function(err) {
        if (err) {
            console.error("Copy Error occured: " + err);
            throw new Error("Failed to generate languages.json");
        }
    });
    if (verbose) {
        console.log("Generated languages.json");
    }
}

/**
 * Convert translation key from weblate format
 * (which only supports a single level) to counterpart
 * which requires object values for 'count' translations.
 *
 * eg.
 *     "there are %(count)s badgers|one": "a badger",
 *     "there are %(count)s badgers|other": "%(count)s badgers"
 *   becomes
 *     "there are %(count)s badgers": {
 *         "one": "a badger",
 *         "other": "%(count)s badgers"
 *     }
 */
function weblateToCounterpart(inTrs) {
    const outTrs = {};

    for (const key of Object.keys(inTrs)) {
        const keyParts = key.split('|', 2);
        if (keyParts.length === 2) {
            let obj = outTrs[keyParts[0]];
            if (obj === undefined) {
                obj = {};
                outTrs[keyParts[0]] = obj;
            }
            obj[keyParts[1]] = inTrs[key];
        } else {
            outTrs[key] = inTrs[key];
        }
    }

    return outTrs;
}

/**
watch the input files for a given language,
regenerate the file, adding its content-hashed filename to langFileMap
and regenerating languages.json with the new filename
*/
function watchLanguage(lang, dest, langFileMap) {
    const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + lang + '.json';
    const riotWebFile = 'src/i18n/strings/' + lang + '.json';

    // XXX: Use a debounce because for some reason if we read the language
    // file immediately after the FS event is received, the file contents
    // appears empty. Possibly https://github.com/nodejs/node/issues/6112
    let makeLangDebouncer;
    const makeLang = () => {
        if (makeLangDebouncer) {
            clearTimeout(makeLangDebouncer);
        }
        makeLangDebouncer = setTimeout(() => {
            const filename = genLangFile(lang, dest);
            langFileMap[lang]=filename;
            genLangList(langFileMap);
        }, 500);
    };

    [reactSdkFile, riotWebFile].forEach(function(f) {
        chokidar.watch(f)
            .on('add', makeLang)
            .on('change', makeLang)
            .on('error', errCheck);
    });
}

// language resources
const I18N_DEST = "webapp/i18n/";
const I18N_FILENAME_MAP = INCLUDE_LANGS.reduce((m, l) => {
    const filename = genLangFile(l.value, I18N_DEST);
    m[l.value] = filename;
    return m;
}, {});
genLangList(I18N_FILENAME_MAP);

if (watch) {
    INCLUDE_LANGS.forEach(l => watchLanguage(l.value, I18N_DEST, I18N_FILENAME_MAP));
}

// non-language resources
next(0);
<|endoftext|>


<commit_before>/**
 * Created by paipeng on 28.05.15.
 */

'use strict';

//var routingConfig;
var fifaApp = angular.module('fifaApp', [
    'ui.router',
    'ngResource',
    'ui.bootstrap',
    'fifa.RankingModule',
    'weather.Module'
]);

fifaApp.config(['$stateProvider', '$urlRouterProvider',
    function ($stateProvider, $urlRouterProvider) {

        $stateProvider.state('home', {
            url: '/home',
            templateUrl: '/views/home.html'
        });
        $stateProvider.state('about', {
            url: '/about',
            templateUrl: '/views/about.html'
        });

    }
])
    .run(['$state', '$rootScope', function ($state, $rootScope) {
        $state.transitionTo('home');

        $rootScope.menuList = [];
        initMenu();

        function initMenu() {
            console.log("initMenu");
            console.log("output loaded modules " + fifaApp.requires);
            var loaded_modules = fifaApp.requires;
            //var modules = loaded_modules.split(',');
            angular.forEach(loaded_modules, function(value, key) {
                if (value === 'weather.Module') {
                    $rootScope.menuList.push({name: 'Weather', url: '/weather'});
                } else if (value === 'fifa.RankingModule') {
                    $rootScope.menuList.push({name: 'Fifa Ranking', url: '/ranking'});
                }
            })
            console.log("modules " + loaded_modules[0]);

        }

    }])
;<commit_msg>update path<commit_after>/**
 * Created by paipeng on 28.05.15.
 */

'use strict';

//var routingConfig;
var fifaApp = angular.module('fifaApp', [
    'ui.router',
    'ngResource',
    'ui.bootstrap',
    'fifa.RankingModule',
    'weather.Module'
]);

fifaApp.config(['$stateProvider', '$urlRouterProvider',
    function ($stateProvider, $urlRouterProvider) {

        $stateProvider.state('home', {
            url: '/home',
            templateUrl: 'views/home.html'
        });
        $stateProvider.state('about', {
            url: '/about',
            templateUrl: 'views/about.html'
        });

    }
])
    .run(['$state', '$rootScope', function ($state, $rootScope) {
        $state.transitionTo('home');

        $rootScope.menuList = [];
        initMenu();

        function initMenu() {
            console.log("initMenu");
            console.log("output loaded modules " + fifaApp.requires);
            var loaded_modules = fifaApp.requires;
            //var modules = loaded_modules.split(',');
            angular.forEach(loaded_modules, function(value, key) {
                if (value === 'weather.Module') {
                    $rootScope.menuList.push({name: 'Weather', url: '/weather'});
                } else if (value === 'fifa.RankingModule') {
                    $rootScope.menuList.push({name: 'Fifa Ranking', url: '/ranking'});
                }
            })
            console.log("modules " + loaded_modules[0]);

        }

    }])
;
<|endoftext|>