<commit_before>/*!
 * ${copyright}
 */

/////////////////////
//// OPA - One Page Acceptance testing
//// Currently this is distributed with UI5 but it does not have dependencies to it.
//// The only dependency is jQuery. As i plan to get this into a separate repository, i did not use the UI5 naming conventions
/////////////////////
(function ($) {
	///////////////////////////////
	/// Privates
	///////////////////////////////
	var queue = [],
		context = {};

	function internalWait (fnCallback, oOptions, oDeferred) {

		// Increase the wait timeout in debug mode, to allow debugging the waitFor without getting timeouts
		if (window["sap-ui-debug"]){
			oOptions.timeout = 300;
		}

		var startTime = new Date(),
			sId = setInterval(function () {

				var oResult = fnCallback();

				if (oResult.result) {
					clearInterval(sId);
					internalEmpty(oDeferred, sId);
				}

				var timeDiff = new Date() - startTime;

				// strip the milliseconds
				timeDiff /= 1000;

				var iPassedSeconds = Math.round(timeDiff % 60);

				if (oOptions.timeout > iPassedSeconds) {
					// timeout not yet reached
					return;
				}

				clearInterval(sId);

				if (oOptions.error) {
					try {
						oOptions.error(oOptions, oResult.arguments);
					} finally {
						oDeferred.reject(oOptions, oResult.arguments);
					}
					return;
				}

				oDeferred.reject(oOptions);
			}, oOptions.pollingInterval);
	}

	function internalEmpty(deferred, sId) {
		if (queue.length === 0) {
			deferred.resolve();
			return true;
		}

		var queueElement = queue.shift();

		internalWait(queueElement.callback, queueElement.options, deferred);
	}

	function ensureNewlyAddedWaitForStatementsPrepended(iPreviousQueueLength, nestedInOptions){
		var iNewWaitForsCount = queue.length - iPreviousQueueLength;
		if (iNewWaitForsCount) {
			var aNewWaitFors = queue.splice(iPreviousQueueLength, iNewWaitForsCount);
			aNewWaitFors.forEach(function(queueElement) {
				queueElement.options._nestedIn = nestedInOptions;
			});
			queue = aNewWaitFors.concat(queue);
		}
	}

	function createStack(iDropCount) {
		iDropCount = (iDropCount || 0) + 2;

		var oError = new Error();
		if (!oError.stack){
			//In IE an error has to be thrown first to get a stack
			try {
				throw oError()
			}catch(oError2){
				//Nothing
			}
		}
		var stack = oError.stack.split("\n");
		stack.splice(0, iDropCount);
		return stack.join("\n");
	}
	///////////////////////////////
	/// Public
	///////////////////////////////

	/**
	 * @class One Page Acceptance testing.
	 * This class will help you write acceptance tests in one page or single page applications.
	 * You can wait for certain conditions to be met.
	 *
	 * @public
	 * @alias sap.ui.test.Opa
	 * @author SAP SE
	 * @since 1.22
	 *
	 * @param extensionObject An object containing properties and functions. The newly created Opa will be extended by these properties and functions - see jQuery.extend.
	 */
	var Opa = function(extensionObject) {

		this.and = this;
		$.extend(this, extensionObject);

	};

	Opa.prototype = {

		/**
		 * Gives access to a singleton object you can save values in.
		 *
		 * @returns {object} the context object
		 * @public
		 */
		getContext : function () {
			return context;
		},

		/**
		 * Waits for a check condition to return true. Then a success function will be called.
		 * If check does not return true until timeout is reached, an error function will be called.
		 *
		 * @public
		 * @param {object} options containing check, success and error function;
		 * properties:
		 *

		 *
timeout: default 15 (seconds) specifies how long the waitFor function polls before it fails

		 *
pollingInterval: default 400 (milliseconds) specifies how often the waitFor function polls

		 *
check: function will get invoked in every polling interval. If it returns true, the check is successful and the polling will stop

		 *
success: function will get invoked after the check function returns true. If there is no check function defined, it will be directly invoked. waitFor statements added in the success handler will be executed before previously added waitFor statements

		 *
error: function will get invoked, when the timeout is reached and check did never return a true.

		 *

		 * @returns {jQuery.promise} a promise that gets resolved on success.
		 */
		waitFor : function (options) {
			var deferred = $.Deferred();
			options = $.extend({},
				Opa.config,
				options);

			options._stack = createStack(1 + options._stackDropCount);
			delete options._stackDropCount;

			deferred.promise(this);

			queue.push({
				callback : jQuery.proxy(function () {
					var bResult = true;

					//no check - all ok
					if (options.check) {
						bResult = options.check.apply(this, arguments);
					}

					if (bResult) {
						if (options.success) {
							try {
								var iCurrentQueueLength = queue.length;
								options.success.apply(this, arguments);
							} finally {
								ensureNewlyAddedWaitForStatementsPrepended(iCurrentQueueLength, options);
								deferred.resolve();
							}
						} else {
							deferred.resolve();
						}

						return { result : true, arguments : arguments };
					}

					return {result : false, arguments : arguments };
				}, this),
				options : options
			});

			return this;
		},

		/**
		 * Calls the static extendConfig function in the Opa namespace
		 * @returns
		 * @public
		 */
		extendConfig : function() {
			return Opa.extendConfig.apply(this, arguments);
		},

		/**
		 * Calls the static emptyQueue function in the Opa namespace
		 * @returns
		 * @public
		 */
		emptyQueue : function() {
			return Opa.emptyQueue.apply(this, arguments);
		}
	};

	/**
	 * Extends and overwrites default values of the Opa.config
	 *
	 * @param {object} options the values to be added to the existion config
	 * @public
	 */
	Opa.extendConfig = function (options) {
		Opa.config = jQuery.extend(Opa.config, options);
	};

	/**
	 * Reset Opa.config to its default values
	 *
	 * @public
	 * @since 1.25
	 */
	Opa.resetConfig = function () {
		Opa.config = {
				arrangements : new Opa(),
				actions : new Opa(),
				assertions : new Opa(),
				timeout : 15,
				pollingInterval : 400,
				_stackDropCount : 0 //Internal use. Specify numbers of additional stack frames to remove for logging
		};
	};
	/**
	 * Waits until all waitFor calls are done
	 *
	 * @returns {jQuery.promise} If the waiting was successful, the promise will be resolved. If not it will be rejected
	 * @public
	 */
	Opa.emptyQueue = function emptyQueue () {
		function addStacks(oOptions) {
			var sResult = "\nCallstack:\n";
			if (oOptions._stack) {
				sResult += oOptions._stack;
				delete oOptions._stack;
			} else {
				sResult += "Unknown";
			}
			if (oOptions._nestedIn) {
				sResult += addStacks(oOptions._nestedIn);
				delete oOptions._nestedIn;
			}
			return sResult;
		}

		var deferred = $.Deferred();

		internalEmpty(deferred);

		return deferred.promise().fail(function(oOptions){
			oOptions.errorMessage = oOptions.errorMessage || "Failed to wait for check";
			oOptions.errorMessage += addStacks(oOptions);
			jQuery.sap.log.error(oOptions.errorMessage);
		});
	};

	if (!sap) {
		sap = {};
	}
	if (!sap.ui) {
		sap.ui = {};
	}
	if (!sap.ui.test) {
		sap.ui.test = {};
	}

	sap.ui.test.Opa = Opa;

	/**
	 * the global configuration of Opa.
	 * All of the global values can be overwritten in an individual waitFor call.
	 * defaults are :
	 *

	 *
timeout : 15 seconds, is increased to 5 minutes if running in debug mode e.g. with URL parameter sap-ui-debug=true

	 *
pollingIntervall: 400 milliseconds

	 *

	 * @public
	 */
	//create the default config
	Opa.resetConfig();
})(jQuery);
<commit_msg>[INTERNAL] sap.ui.test.OPA - fixing stacktrace in IE's<commit_after>/*!
 * ${copyright}
 */

/////////////////////
//// OPA - One Page Acceptance testing
//// Currently this is distributed with UI5 but it does not have dependencies to it.
//// The only dependency is jQuery. As i plan to get this into a separate repository, i did not use the UI5 naming conventions
/////////////////////
(function ($) {
	///////////////////////////////
	/// Privates
	///////////////////////////////
	var queue = [],
		context = {};

	function internalWait (fnCallback, oOptions, oDeferred) {

		// Increase the wait timeout in debug mode, to allow debugging the waitFor without getting timeouts
		if (window["sap-ui-debug"]){
			oOptions.timeout = 300;
		}

		var startTime = new Date(),
			sId = setInterval(function () {

				var oResult = fnCallback();

				if (oResult.result) {
					clearInterval(sId);
					internalEmpty(oDeferred, sId);
				}

				var timeDiff = new Date() - startTime;

				// strip the milliseconds
				timeDiff /= 1000;

				var iPassedSeconds = Math.round(timeDiff % 60);

				if (oOptions.timeout > iPassedSeconds) {
					// timeout not yet reached
					return;
				}

				clearInterval(sId);

				if (oOptions.error) {
					try {
						oOptions.error(oOptions, oResult.arguments);
					} finally {
						oDeferred.reject(oOptions, oResult.arguments);
					}
					return;
				}

				oDeferred.reject(oOptions);
			}, oOptions.pollingInterval);
	}

	function internalEmpty(deferred, sId) {
		if (queue.length === 0) {
			deferred.resolve();
			return true;
		}

		var queueElement = queue.shift();

		internalWait(queueElement.callback, queueElement.options, deferred);
	}

	function ensureNewlyAddedWaitForStatementsPrepended(iPreviousQueueLength, nestedInOptions){
		var iNewWaitForsCount = queue.length - iPreviousQueueLength;
		if (iNewWaitForsCount) {
			var aNewWaitFors = queue.splice(iPreviousQueueLength, iNewWaitForsCount);
			aNewWaitFors.forEach(function(queueElement) {
				queueElement.options._nestedIn = nestedInOptions;
			});
			queue = aNewWaitFors.concat(queue);
		}
	}

	function createStack(iDropCount) {
		iDropCount = (iDropCount || 0) + 2;

		var oError = new Error();
		var stack = oError.stack;
		if (!stack){
			//In IE an error has to be thrown first to get a stack
			try {
				throw oError()
			}catch(oError2){
				stack = oError2.stack;
			}
		}

		// IE <= 9 this will not work
		if (!stack) {
			return "";
		}

		stack = stack.split("\n");
		stack.splice(0, iDropCount);
		return stack.join("\n");
	}
	///////////////////////////////
	/// Public
	///////////////////////////////

	/**
	 * @class One Page Acceptance testing.
	 * This class will help you write acceptance tests in one page or single page applications.
	 * You can wait for certain conditions to be met.
	 *
	 * @public
	 * @alias sap.ui.test.Opa
	 * @author SAP SE
	 * @since 1.22
	 *
	 * @param extensionObject An object containing properties and functions. The newly created Opa will be extended by these properties and functions - see jQuery.extend.
	 */
	var Opa = function(extensionObject) {

		this.and = this;
		$.extend(this, extensionObject);

	};

	Opa.prototype = {

		/**
		 * Gives access to a singleton object you can save values in.
		 *
		 * @returns {object} the context object
		 * @public
		 */
		getContext : function () {
			return context;
		},

		/**
		 * Waits for a check condition to return true. Then a success function will be called.
		 * If check does not return true until timeout is reached, an error function will be called.
		 *
		 * @public
		 * @param {object} options containing check, success and error function;
		 * properties:
		 *

		 *
timeout: default 15 (seconds) specifies how long the waitFor function polls before it fails

		 *
pollingInterval: default 400 (milliseconds) specifies how often the waitFor function polls

		 *
check: function will get invoked in every polling interval. If it returns true, the check is successful and the polling will stop

		 *
success: function will get invoked after the check function returns true. If there is no check function defined, it will be directly invoked. waitFor statements added in the success handler will be executed before previously added waitFor statements

		 *
error: function will get invoked, when the timeout is reached and check did never return a true.

		 *

		 * @returns {jQuery.promise} a promise that gets resolved on success.
		 */
		waitFor : function (options) {
			var deferred = $.Deferred();
			options = $.extend({},
				Opa.config,
				options);

			options._stack = createStack(1 + options._stackDropCount);
			delete options._stackDropCount;

			deferred.promise(this);

			queue.push({
				callback : jQuery.proxy(function () {
					var bResult = true;

					//no check - all ok
					if (options.check) {
						bResult = options.check.apply(this, arguments);
					}

					if (bResult) {
						if (options.success) {
							try {
								var iCurrentQueueLength = queue.length;
								options.success.apply(this, arguments);
							} finally {
								ensureNewlyAddedWaitForStatementsPrepended(iCurrentQueueLength, options);
								deferred.resolve();
							}
						} else {
							deferred.resolve();
						}

						return { result : true, arguments : arguments };
					}

					return {result : false, arguments : arguments };
				}, this),
				options : options
			});

			return this;
		},

		/**
		 * Calls the static extendConfig function in the Opa namespace
		 * @returns
		 * @public
		 */
		extendConfig : function() {
			return Opa.extendConfig.apply(this, arguments);
		},

		/**
		 * Calls the static emptyQueue function in the Opa namespace
		 * @returns
		 * @public
		 */
		emptyQueue : function() {
			return Opa.emptyQueue.apply(this, arguments);
		}
	};

	/**
	 * Extends and overwrites default values of the Opa.config
	 *
	 * @param {object} options the values to be added to the existion config
	 * @public
	 */
	Opa.extendConfig = function (options) {
		Opa.config = jQuery.extend(Opa.config, options);
	};

	/**
	 * Reset Opa.config to its default values
	 *
	 * @public
	 * @since 1.25
	 */
	Opa.resetConfig = function () {
		Opa.config = {
				arrangements : new Opa(),
				actions : new Opa(),
				assertions : new Opa(),
				timeout : 15,
				pollingInterval : 400,
				_stackDropCount : 0 //Internal use. Specify numbers of additional stack frames to remove for logging
		};
	};
	/**
	 * Waits until all waitFor calls are done
	 *
	 * @returns {jQuery.promise} If the waiting was successful, the promise will be resolved. If not it will be rejected
	 * @public
	 */
	Opa.emptyQueue = function emptyQueue () {
		function addStacks(oOptions) {
			var sResult = "\nCallstack:\n";
			if (oOptions._stack) {
				sResult += oOptions._stack;
				delete oOptions._stack;
			} else {
				sResult += "Unknown";
			}
			if (oOptions._nestedIn) {
				sResult += addStacks(oOptions._nestedIn);
				delete oOptions._nestedIn;
			}
			return sResult;
		}

		var deferred = $.Deferred();

		internalEmpty(deferred);

		return deferred.promise().fail(function(oOptions){
			oOptions.errorMessage = oOptions.errorMessage || "Failed to wait for check";
			oOptions.errorMessage += addStacks(oOptions);
			jQuery.sap.log.error(oOptions.errorMessage);
		});
	};

	if (!sap) {
		sap = {};
	}
	if (!sap.ui) {
		sap.ui = {};
	}
	if (!sap.ui.test) {
		sap.ui.test = {};
	}

	sap.ui.test.Opa = Opa;

	/**
	 * the global configuration of Opa.
	 * All of the global values can be overwritten in an individual waitFor call.
	 * defaults are :
	 *

	 *
timeout : 15 seconds, is increased to 5 minutes if running in debug mode e.g. with URL parameter sap-ui-debug=true

	 *
pollingIntervall: 400 milliseconds

	 *

	 * @public
	 */
	//create the default config
	Opa.resetConfig();
})(jQuery);
<|endoftext|>


<commit_before>'use strict'

const grpc = require('grpc')
const deepclone = require('deepclone')
const persist = require('./persist.js')
const authsession = require('./authsession.js')
const dispatcher = require('./dispatcher.js')

class SubscribeHandlers {
  'PapanLobby.WhisperChatMessage' (call, data) {
    const id = authsession.getId(call)
    const message = deepclone(data)
    message.id = id
    persist.sendMessage(data.id, { message: message })
  }

  'PapanLobby.GetJoinedLobbies' (call, data) {
    const id = authsession.getId(call)
    return persist.getJoinedLobbies({ id: id })
    .then(result => {
      call.write({
        joinedLobbies: {
          lobbies: result
        }
      })
    })
  }
}

class LobbyHandlers {
  'PapanLobby.JoinLobby' (call, data) {
    const userId = authsession.getId(call)
    let id = data.id
    let premise
    if (id) {
      premise = persist.joinLobby({
        userId: userId,
        id: id
      })
    } else {
      premise = persist.createLobby({
        userId: userId
      })
    }
    return premise
    .then(result => {
      id = result.id
      call.id = id
      const sub = persist.lobbySubscribe(id, message => {
        call.write(message)
      })
      call.on('end', () => sub.close())
      call.write({
        info: result
      })
      persist.lobbySendMessage(id, {
        userJoined: {
          id: userId
        }
      })
    })
  }

  'PapanLobby.SetLobbyName' (call, data) {
    const userId = authsession.getId(call)
    return persist.setLobbyName({
      userId: userId,
      id: call.id,
      name: data.setName.name
    })
    .then(result => {
      persist.lobbySendMessage({
        info: result
      })
    })
  }

  'PapanLobby.SetLobbyPublic' (call, data) {
    const userId = authsession.getId(call)
    return persist.setLobbyPublic({
      userId: userId,
      id: call.id,
      public: data.setPublic.public
    }).then(result => {
      persist.lobbySendMessage({
        info: result
      })
    })
  }

  'PapanLobby.LeaveLobby' (call, data) { return Promise.reject(Error('Unimplemented')) }

  'PapanLobby.LobbyChatMessage' (call, data) {
    data.message.user = { id: authsession.getId(call) }
    persist.lobbySendMessage(call.id, { message: data })
  }

  'PapanLobby.SetReady' (call, data) { return Promise.reject(Error('Unimplemented')) }
  'PapanLobby.KickUser' (call, data) { return Promise.reject(Error('Unimplemented')) }
  'PapanLobby.SetLobbyGame' (call, data) { return Promise.reject(Error('Unimplemented')) }
}

const Subscribe = (call, dispatcher) => {
  const id = authsession.getId(call)
  call.write({
    subscribed: {
      self: {
        id: id
      }
    }
  })
  const sub = persist.userSubscribe(id, call.write)
  call.on('data', data => dispatcher(call, data))
  call.on('end', () => {
    sub.close()
    call.end()
  })
}

const Lobby = (call, dispatcher) => {
  let gotJoin = false
  call.on('end', () => call.end())
  call.on('data', data => {
    let joinError = false
    let errorMsg
    if (data.action === 'join') {
      if (gotJoin) {
        joinError = true
        errorMsg = 'You can\'t join twice'
      }
      gotJoin = true
    } else {
      if (!gotJoin) {
        joinError = true
        errorMsg = 'You need to join first'
      }
    }
    if (joinError) {
      let error = {
        code: grpc.status.FAILED_PRECONDITION,
        details: errorMsg,
        metadata: new grpc.Metadata()
      }
      call.emit('error', error)
      call.end()
    } else {
      dispatcher(call, data)
    }
  })
}

const ListLobbies = call => {
  const sub = persist.lobbyListSubscribe(data => {
    call.write(data)
  })
  persist.getPublicLobbies()
  .then(lobbies => {
    if (!lobbies) lobbies = []
    return Promise.all(lobbies.map(id => persist.getLobbyInfo({ id: id })))
  })
  .then(lobbies => {
    lobbies.forEach(info => {
      call.write({
        lobby: info,
        status: 0
      })
    })
  })
  call.on('end', () => {
    sub.close()
    call.end()
  })
}

exports.generateService = (proto, options) => {
  const subscribeDispatcher = dispatcher(proto.Action.fields, new SubscribeHandlers())
  const lobbyDispatcher = dispatcher(proto.LobbyAction.fields, new LobbyHandlers())
  return {
    Subscribe: call => Subscribe(call, subscribeDispatcher),
    Lobby: call => Lobby(call, lobbyDispatcher),
    ListLobbies: ListLobbies
  }
}
<commit_msg>Typos.<commit_after>'use strict'

const grpc = require('grpc')
const deepclone = require('deepclone')
const persist = require('./persist.js')
const authsession = require('./authsession.js')
const dispatcher = require('./dispatcher.js')

class SubscribeHandlers {
  'PapanLobby.WhisperChatMessage' (call, data) {
    const id = authsession.getId(call)
    const message = deepclone(data)
    message.id = id
    persist.sendMessage(data.id, { message: message })
  }

  'PapanLobby.GetJoinedLobbies' (call, data) {
    const id = authsession.getId(call)
    return persist.getJoinedLobbies({ id: id })
    .then(result => {
      call.write({
        joinedLobbies: {
          lobbies: result
        }
      })
    })
  }
}

class LobbyHandlers {
  'PapanLobby.JoinLobby' (call, data) {
    const userId = authsession.getId(call)
    let id = data.id
    let premise
    if (id) {
      premise = persist.joinLobby({
        userId: userId,
        id: id
      })
    } else {
      premise = persist.createLobby({
        userId: userId
      })
    }
    return premise
    .then(result => {
      id = result.id
      call.id = id
      const sub = persist.lobbySubscribe(id, message => {
        call.write(message)
      })
      call.on('end', () => sub.close())
      call.write({
        info: result
      })
      persist.lobbySendMessage(id, {
        userJoined: {
          id: userId
        }
      })
    })
  }

  'PapanLobby.SetLobbyName' (call, data) {
    const userId = authsession.getId(call)
    return persist.setLobbyName({
      userId: userId,
      id: call.id,
      name: data.setName.name
    })
    .then(result => {
      persist.lobbySendMessage(call.id, {
        info: result
      })
    })
  }

  'PapanLobby.SetLobbyPublic' (call, data) {
    const userId = authsession.getId(call)
    return persist.setLobbyPublic({
      userId: userId,
      id: call.id,
      public: data.setPublic.public
    }).then(result => {
      persist.lobbySendMessage(call.id, {
        info: result
      })
    })
  }

  'PapanLobby.LeaveLobby' (call, data) { return Promise.reject(Error('Unimplemented')) }

  'PapanLobby.LobbyChatMessage' (call, data) {
    data.message.user = { id: authsession.getId(call) }
    persist.lobbySendMessage(call.id, { message: data })
  }

  'PapanLobby.SetReady' (call, data) { return Promise.reject(Error('Unimplemented')) }
  'PapanLobby.KickUser' (call, data) { return Promise.reject(Error('Unimplemented')) }
  'PapanLobby.SetLobbyGame' (call, data) { return Promise.reject(Error('Unimplemented')) }
}

const Subscribe = (call, dispatcher) => {
  const id = authsession.getId(call)
  call.write({
    subscribed: {
      self: {
        id: id
      }
    }
  })
  const sub = persist.userSubscribe(id, call.write)
  call.on('data', data => dispatcher(call, data))
  call.on('end', () => {
    sub.close()
    call.end()
  })
}

const Lobby = (call, dispatcher) => {
  let gotJoin = false
  call.on('end', () => call.end())
  call.on('data', data => {
    let joinError = false
    let errorMsg
    if (data.action === 'join') {
      if (gotJoin) {
        joinError = true
        errorMsg = 'You can\'t join twice'
      }
      gotJoin = true
    } else {
      if (!gotJoin) {
        joinError = true
        errorMsg = 'You need to join first'
      }
    }
    if (joinError) {
      let error = {
        code: grpc.status.FAILED_PRECONDITION,
        details: errorMsg,
        metadata: new grpc.Metadata()
      }
      call.emit('error', error)
      call.end()
    } else {
      dispatcher(call, data)
    }
  })
}

const ListLobbies = call => {
  const sub = persist.lobbyListSubscribe(data => {
    call.write(data)
  })
  persist.getPublicLobbies()
  .then(lobbies => {
    if (!lobbies) lobbies = []
    return Promise.all(lobbies.map(id => persist.getLobbyInfo({ id: id })))
  })
  .then(lobbies => {
    lobbies.forEach(info => {
      call.write({
        lobby: info,
        status: 0
      })
    })
  })
  call.on('end', () => {
    sub.close()
    call.end()
  })
}

exports.generateService = (proto, options) => {
  const subscribeDispatcher = dispatcher(proto.Action.fields, new SubscribeHandlers())
  const lobbyDispatcher = dispatcher(proto.LobbyAction.fields, new LobbyHandlers())
  return {
    Subscribe: call => Subscribe(call, subscribeDispatcher),
    Lobby: call => Lobby(call, lobbyDispatcher),
    ListLobbies: ListLobbies
  }
}
<|endoftext|>


<commit_before>import { fitin } from 'universal/utils/object';

/**
 * @type {import('./version').VersionModule}
 */
const mod = {
    state: {
        /**
         * local versions
         */
        local: [],
        refreshingMinecraft: false,
        refreshingForge: false,
        refreshingLiteloader: false,
        minecraft: {
            timestamp: '',
            latest: {
                snapshot: '',
                release: '',
            },
            versions: [],
        },
        forge: {

        },
        liteloader: {
            timestamp: '',
            meta: {
                description: '',
                authors: '',
                url: '',
                updated: '',
                updatedTime: 0,
            },
            versions: {},
        },
    },
    getters: {
        /**
         * latest snapshot
         */
        minecraftSnapshot: state => state.minecraft.versions.find(v => v.id === state.minecraft.latest.snapshot),
        /**
         * latest release
         */
        minecraftRelease: state => state.minecraft.versions.find(v => v.id === state.minecraft.latest.release),

        minecraftVersion: state => version => state.minecraft.versions.find(v => v.id === version),

        minecraftStatuses: (state, _, rootStates) => {
            /**
             * @type {{[k:string]:boolean}}
             */
            const localVersions = {};
            rootStates.version.local.forEach((ver) => {
                if (ver.minecraft) localVersions[ver.minecraft] = true;
            });
            /**
             * @type {{[key:string]: import('./version').Status}}
             */
            const statusMap = {};
            for (const ver of state.minecraft.versions) {
                statusMap[ver.id] = localVersions[ver.id] ? 'local' : 'remote';
            }
            return statusMap;
        },
        forgeVersionsOf: state => version => (state.forge[version]),
        forgeLatestOf: state => (version) => {
            const versions = state.forge[version];
            return versions.versions.find(v => v.type === 'latest');
        },
        forgeRecommendedOf: state => (version) => {
            const versions = state.forge[version];
            return versions.versions.find(v => v.type === 'recommended');
        },
        forgeStatuses: (state, _, rootState) => {
            /**
             * @type {{[key:string]: import('./version').Status}}
             */
            const statusMap = {};
            /**
            * @type {{[k:string]:boolean}}
            */
            const localForgeVersion = {};
            rootState.version.local.forEach((ver) => {
                if (ver.forge) localForgeVersion[ver.forge] = true;
            });

            Object.keys(state.forge).forEach((mcversion) => {
                const container = state.forge[mcversion];
                if (container.versions) {
                    container.versions.forEach((version) => {
                        statusMap[version.version] = localForgeVersion[version.version] ? 'local' : 'remote';
                    });
                }
            });
            return statusMap;
        },
        liteloaderVersionsOf: state => version => state.liteloader.versions[version],
    },
    mutations: {
        refreshingMinecraft(state, r) { state.refreshingMinecraft = r; },
        refreshingForge(state, r) { state.refreshingForge = r; },
        refreshingLiteloader(state, r) { state.refreshingLiteloader = r; },

        localVersions(state, local) {
            state.local = local;
        },
        minecraftMetadata(state, metadata) {
            fitin(state.minecraft, metadata);
        },
        forgeMetadata(state, metadata) {
            const { mcversion, versions } = metadata;
            // const container = state.forge[mcversion] || {};
            // container.timestamp = metadata.timestamp;

            // let latest = 0;
            // let recommended = 0;
            // for (let i = 0; i < versions.length; i++) {
            //     const version = versions[i];
            //     if (version.type === 'recommended') recommended = i;
            //     else if (version.type === 'latest') latest = i;
            // }
            // container.versions = versions;
            // container.mcversion = mcversion;
            // container.latest = latest;
            // container.recommended = recommended;

            state.forge[mcversion] = metadata;
        },
        liteloaderMetadata(state, metadata) {
            fitin(state.liteloader, metadata);
        },
    },
};

export default mod;
<commit_msg>fix: prevent nullptr err one getting forge<commit_after>import { fitin } from 'universal/utils/object';

/**
 * @type {import('./version').VersionModule}
 */
const mod = {
    state: {
        /**
         * local versions
         */
        local: [],
        refreshingMinecraft: false,
        refreshingForge: false,
        refreshingLiteloader: false,
        minecraft: {
            timestamp: '',
            latest: {
                snapshot: '',
                release: '',
            },
            versions: [],
        },
        forge: {

        },
        liteloader: {
            timestamp: '',
            meta: {
                description: '',
                authors: '',
                url: '',
                updated: '',
                updatedTime: 0,
            },
            versions: {},
        },
    },
    getters: {
        /**
         * latest snapshot
         */
        minecraftSnapshot: state => state.minecraft.versions.find(v => v.id === state.minecraft.latest.snapshot),
        /**
         * latest release
         */
        minecraftRelease: state => state.minecraft.versions.find(v => v.id === state.minecraft.latest.release),

        minecraftVersion: state => version => state.minecraft.versions.find(v => v.id === version),

        minecraftStatuses: (state, _, rootStates) => {
            /**
             * @type {{[k:string]:boolean}}
             */
            const localVersions = {};
            rootStates.version.local.forEach((ver) => {
                if (ver.minecraft) localVersions[ver.minecraft] = true;
            });
            /**
             * @type {{[key:string]: import('./version').Status}}
             */
            const statusMap = {};
            for (const ver of state.minecraft.versions) {
                statusMap[ver.id] = localVersions[ver.id] ? 'local' : 'remote';
            }
            return statusMap;
        },
        forgeVersionsOf: state => version => (state.forge[version]),
        forgeLatestOf: state => (version) => {
            const versions = state.forge[version];
            if (!versions) return undefined;
            return versions.versions.find(v => v.type === 'latest');
        },
        forgeRecommendedOf: state => (version) => {
            const versions = state.forge[version];
            if (!versions) return undefined;
            return versions.versions.find(v => v.type === 'recommended');
        },
        forgeStatuses: (state, _, rootState) => {
            /**
             * @type {{[key:string]: import('./version').Status}}
             */
            const statusMap = {};
            /**
            * @type {{[k:string]:boolean}}
            */
            const localForgeVersion = {};
            rootState.version.local.forEach((ver) => {
                if (ver.forge) localForgeVersion[ver.forge] = true;
            });

            Object.keys(state.forge).forEach((mcversion) => {
                const container = state.forge[mcversion];
                if (container.versions) {
                    container.versions.forEach((version) => {
                        statusMap[version.version] = localForgeVersion[version.version] ? 'local' : 'remote';
                    });
                }
            });
            return statusMap;
        },
        liteloaderVersionsOf: state => version => state.liteloader.versions[version],
    },
    mutations: {
        refreshingMinecraft(state, r) { state.refreshingMinecraft = r; },
        refreshingForge(state, r) { state.refreshingForge = r; },
        refreshingLiteloader(state, r) { state.refreshingLiteloader = r; },

        localVersions(state, local) {
            state.local = local;
        },
        minecraftMetadata(state, metadata) {
            fitin(state.minecraft, metadata);
        },
        forgeMetadata(state, metadata) {
            const { mcversion, versions } = metadata;
            // const container = state.forge[mcversion] || {};
            // container.timestamp = metadata.timestamp;

            // let latest = 0;
            // let recommended = 0;
            // for (let i = 0; i < versions.length; i++) {
            //     const version = versions[i];
            //     if (version.type === 'recommended') recommended = i;
            //     else if (version.type === 'latest') latest = i;
            // }
            // container.versions = versions;
            // container.mcversion = mcversion;
            // container.latest = latest;
            // container.recommended = recommended;

            state.forge[mcversion] = metadata;
        },
        liteloaderMetadata(state, metadata) {
            fitin(state.liteloader, metadata);
        },
    },
};

export default mod;
<|endoftext|>


<commit_before>export default function composeQuery({ type, word }) {
  const queryStr = type === 'entry'
    ? 'dictionary/' : type === 'search'
    ? 'search/?q='
    : 'search/?q=';

  return `https://query.yahooapis.com/v1/public/yql?q=${encodeURIComponent(
    `SELECT * FROM html WHERE url="http://www.ldoceonline.com/${queryStr}${word}"`
  )}`;
}
<commit_msg>refactor: refactor compose Query<commit_after>export default function composeQuery({ type, word }) {
  const queryStr = type === 'entry'
    ? 'dictionary/'
    : 'search/?q=';

  const dictionaryUrl = `http://www.ldoceonline.com/${queryStr}${word}`;

  const queryUrl = `https://query.yahooapis.com/v1/public/yql?q=${encodeURIComponent(
    `SELECT * FROM html WHERE url="${dictionaryUrl}"`
  )}`;

  return queryUrl;
}
<|endoftext|>


<commit_before>'use strict';

/*
WebsocketRails JavaScript Client

Setting up the dispatcher:
  var dispatcher = new WebSocketRails('localhost:3000/websocket');
  dispatcher.onOpen = function() {
    // trigger a server event immediately after opening connection
    dispatcher.trigger('new_user',{user_name: 'guest'});
  })

Triggering a new event on the server
  dispatcherer.trigger('event_name',object_to_be_serialized_to_json);

Listening for new events from the server
  dispatcher.bind('event_name', function(data) {
    console.log(data.user_name);
  });

Stop listening for new events from the server
  dispatcher.unbind('event')
 */

var __bind = function(fn, me){
      return function(){
        return fn.apply(me, arguments);
      };
    },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) {
      for (var key in parent) {
        if (!__hasProp.call(parent, key)) {
          child[key] = parent[key];
        }
      }

      function Ctor() {
        this.constructor = child;
      }

      Ctor.prototype = parent.prototype;
      child.prototype = new Ctor();
      child.__super__ = parent.prototype;
      return child;
    };

var WebSocketRails = (function() {
  function WebSocketRails(url, useWebsockets) {
    this.url = url;
    this.useWebsockets = useWebsockets !== null ? useWebsockets : true;
    this.connectionStale = __bind(this.connectionStale, this);
    this.supportsWebsockets = __bind(this.supportsWebsockets, this);
    this.dispatchChannel = __bind(this.dispatchChannel, this);
    this.unsubscribe = __bind(this.unsubscribe, this);
    this.subscribePrivate = __bind(this.subscribePrivate, this);
    this.subscribe = __bind(this.subscribe, this);
    this.dispatch = __bind(this.dispatch, this);
    this.triggerEvent = __bind(this.triggerEvent, this);
    this.trigger = __bind(this.trigger, this);
    this.bind = __bind(this.bind, this);
    this.connectionEstablished = __bind(this.connectionEstablished, this);
    this.newMessage = __bind(this.newMessage, this);
    this.reconnect = __bind(this.reconnect, this);
    this.callbacks = {};
    this.channels = {};
    this.queue = {};
    this.connect();
  }

  WebSocketRails.prototype.connect = function() {
    this.state = 'connecting';
    if (!(this.supportsWebsockets() && this.useWebsockets)) {
      this._conn = new WebSocketRails.HttpConnection(this.url, this);
    } else {
      this._conn = new WebSocketRails.WebSocketConnection(this.url, this);
    }
    this._conn.newMessage = this.newMessage;
    return this._conn.newMessage;
  };

  WebSocketRails.prototype.disconnect = function() {
    if (this._conn) {
      this._conn.close();
      delete this._conn._conn;
      delete this._conn;
    }
    this.state = 'disconnected';
    return this.state;
  };

  WebSocketRails.prototype.reconnect = function() {
    var event, id, oldConnectionId, _ref, _ref1;
    oldConnectionId = (_ref = this._conn) !== null ? _ref.connectionId : void 0;
    this.disconnect();
    this.connect();
    _ref1 = this.queue;
    for (id in _ref1) {
      event = _ref1[id];
      if (event.connectionId === oldConnectionId && !event.isResult()) {
        this.triggerEvent(event);
      }
    }
    return this.reconnectChannels();
  };

  WebSocketRails.prototype.newMessage = function(data) {
    var event, _ref;
    event = new WebSocketRails.Event(data);
    if (event.isResult()) {
      if ((_ref = this.queue[event.id]) !== null) {
        _ref.runCallbacks(event.success, event.data);
      }
      this.queue[event.id] = null;
    } else if (event.isChannel()) {
      this.dispatchChannel(event);
    } else {
      this.dispatch(event);
    }
    if (this.state === 'connecting' && event.name === 'client_connected') {
      return this.connectionEstablished(event);
    }
  };

  WebSocketRails.prototype.connectionEstablished = function(event) {
    this.state = 'connected';
    this._conn.setConnectionId(event.connectionId);
    this._conn.flushQueue();
    if (this.onOpen !== null) {
      return this.onOpen(event.data);
    }
  };

  WebSocketRails.prototype.bind = function(eventName, callback) {
    var _base;
    if ((_base = this.callbacks)[eventName] === null) {
      _base[eventName] = [];
    }
    return this.callbacks[eventName].push(callback);
  };

  WebSocketRails.prototype.trigger = function(eventName, data, successCallback, failureCallback) {
    var event;
    event = new WebSocketRails.Event([
      eventName, data, {
        connectionId: this.connectionId
      }
    ], successCallback, failureCallback);
    this.queue[event.id] = event;
    return this._conn.trigger(event);
  };

  WebSocketRails.prototype.triggerEvent = function(event) {
    var _base, _name;
    if ((_base = this.queue)[_name = event.id] === null) {
      _base[_name] = event;
    }
    this._conn.trigger(event);
    return event;
  };

  WebSocketRails.prototype.dispatch = function(event) {
    var callback, _i, _len, _ref, _results;
    if (this.callbacks[event.name] === null) {
      return;
    }
    _ref = this.callbacks[event.name];
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      callback = _ref[_i];
      _results.push(callback(event.data));
    }
    return _results;
  };

  WebSocketRails.prototype.subscribe = function(channelName, successCallback, failureCallback) {
    var channel;
    if (this.channels[channelName] === null) {
      channel = new WebSocketRails.Channel(channelName, this, false, successCallback, failureCallback);
      this.channels[channelName] = channel;
      return channel;
    } else {
      return this.channels[channelName];
    }
  };

  WebSocketRails.prototype.subscribePrivate = function(channelName, successCallback, failureCallback) {
    var channel;
    if (this.channels[channelName] === null) {
      channel = new WebSocketRails.Channel(channelName, this, true, successCallback, failureCallback);
      this.channels[channelName] = channel;
      return channel;
    } else {
      return this.channels[channelName];
    }
  };

  WebSocketRails.prototype.unsubscribe = function(channelName) {
    if (this.channels[channelName] === null) {
      return;
    }
    this.channels[channelName].destroy();
    return delete this.channels[channelName];
  };

  WebSocketRails.prototype.dispatchChannel = function(event) {
    if (this.channels[event.channel] === null) {
      return;
    }
    return this.channels[event.channel].dispatch(event.name, event.data);
  };

  WebSocketRails.prototype.supportsWebsockets = function() {
    return typeof WebSocket === 'function' || typeof WebSocket === 'object';
  };

  WebSocketRails.prototype.connectionStale = function() {
    return this.state !== 'connected';
  };

  WebSocketRails.prototype.reconnectChannels = function() {
    var callbacks, channel, name, _ref, _results;
    _ref = this.channels;
    _results = [];
    for (name in _ref) {
      channel = _ref[name];
      callbacks = channel._callbacks;
      channel.destroy();
      delete this.channels[name];
      channel = channel.isPrivate ? this.subscribePrivate(name) : this.subscribe(name);
      channel._callbacks = callbacks;
      _results.push(channel);
    }
    return _results;
  };

  return WebSocketRails;

})();

WebSocketRails.AbstractConnection = require('./abstract_connection');
WebSocketRails.Channel = require('./channel');
WebSocketRails.Connection = require('./connection');
WebSocketRails.Event = require('./event');
WebSocketRails.HttpConnection = require('./http_connection');
__extends(WebSocketRails.HttpConnection, WebSocketRails.AbstractConnection);
WebSocketRails.WebSocketConnection = require('./websocket_connection');
__extends(WebSocketRails.WebSocketConnection, WebSocketRails.AbstractConnection);

module.exports = WebSocketRails;
<commit_msg>changes to extend<commit_after>'use strict';

/*
WebsocketRails JavaScript Client

Setting up the dispatcher:
  var dispatcher = new WebSocketRails('localhost:3000/websocket');
  dispatcher.onOpen = function() {
    // trigger a server event immediately after opening connection
    dispatcher.trigger('new_user',{user_name: 'guest'});
  })

Triggering a new event on the server
  dispatcherer.trigger('event_name',object_to_be_serialized_to_json);

Listening for new events from the server
  dispatcher.bind('event_name', function(data) {
    console.log(data.user_name);
  });

Stop listening for new events from the server
  dispatcher.unbind('event')
 */

var __bind = function(fn, me){
      return function(){
        return fn.apply(me, arguments);
      };
    },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) {
      for (var key in parent) {
        if (!parent.hasOwnProperty(key)) {
          child[key] = parent[key];
        }
      }

      function Ctor() {
        this.constructor = child;
      }

      Ctor.prototype = parent.prototype;
      child.prototype = new Ctor();
      child.__super__ = parent.prototype;
      return child;
    };

var WebSocketRails = (function() {
  function WebSocketRails(url, useWebsockets) {
    this.url = url;
    this.useWebsockets = useWebsockets !== null ? useWebsockets : true;
    this.connectionStale = __bind(this.connectionStale, this);
    this.supportsWebsockets = __bind(this.supportsWebsockets, this);
    this.dispatchChannel = __bind(this.dispatchChannel, this);
    this.unsubscribe = __bind(this.unsubscribe, this);
    this.subscribePrivate = __bind(this.subscribePrivate, this);
    this.subscribe = __bind(this.subscribe, this);
    this.dispatch = __bind(this.dispatch, this);
    this.triggerEvent = __bind(this.triggerEvent, this);
    this.trigger = __bind(this.trigger, this);
    this.bind = __bind(this.bind, this);
    this.connectionEstablished = __bind(this.connectionEstablished, this);
    this.newMessage = __bind(this.newMessage, this);
    this.reconnect = __bind(this.reconnect, this);
    this.callbacks = {};
    this.channels = {};
    this.queue = {};
    this.connect();
  }

  WebSocketRails.prototype.connect = function() {
    this.state = 'connecting';
    if (!(this.supportsWebsockets() && this.useWebsockets)) {
      this._conn = new WebSocketRails.HttpConnection(this.url, this);
    } else {
      this._conn = new WebSocketRails.WebSocketConnection(this.url, this);
    }
    this._conn.newMessage = this.newMessage;
    return this._conn.newMessage;
  };

  WebSocketRails.prototype.disconnect = function() {
    if (this._conn) {
      this._conn.close();
      delete this._conn._conn;
      delete this._conn;
    }
    this.state = 'disconnected';
    return this.state;
  };

  WebSocketRails.prototype.reconnect = function() {
    var event, id, oldConnectionId, _ref, _ref1;
    oldConnectionId = (_ref = this._conn) !== null ? _ref.connectionId : void 0;
    this.disconnect();
    this.connect();
    _ref1 = this.queue;
    for (id in _ref1) {
      event = _ref1[id];
      if (event.connectionId === oldConnectionId && !event.isResult()) {
        this.triggerEvent(event);
      }
    }
    return this.reconnectChannels();
  };

  WebSocketRails.prototype.newMessage = function(data) {
    var event, _ref;
    event = new WebSocketRails.Event(data);
    if (event.isResult()) {
      if ((_ref = this.queue[event.id]) !== null) {
        _ref.runCallbacks(event.success, event.data);
      }
      this.queue[event.id] = null;
    } else if (event.isChannel()) {
      this.dispatchChannel(event);
    } else {
      this.dispatch(event);
    }
    if (this.state === 'connecting' && event.name === 'client_connected') {
      return this.connectionEstablished(event);
    }
  };

  WebSocketRails.prototype.connectionEstablished = function(event) {
    this.state = 'connected';
    this._conn.setConnectionId(event.connectionId);
    this._conn.flushQueue();
    if (this.onOpen !== null) {
      return this.onOpen(event.data);
    }
  };

  WebSocketRails.prototype.bind = function(eventName, callback) {
    var _base;
    if ((_base = this.callbacks)[eventName] === null) {
      _base[eventName] = [];
    }
    return this.callbacks[eventName].push(callback);
  };

  WebSocketRails.prototype.trigger = function(eventName, data, successCallback, failureCallback) {
    var event;
    event = new WebSocketRails.Event([
      eventName, data, {
        connectionId: this.connectionId
      }
    ], successCallback, failureCallback);
    this.queue[event.id] = event;
    return this._conn.trigger(event);
  };

  WebSocketRails.prototype.triggerEvent = function(event) {
    var _base, _name;
    if ((_base = this.queue)[_name = event.id] === null) {
      _base[_name] = event;
    }
    this._conn.trigger(event);
    return event;
  };

  WebSocketRails.prototype.dispatch = function(event) {
    var callback, _i, _len, _ref, _results;
    if (this.callbacks[event.name] === null) {
      return;
    }
    _ref = this.callbacks[event.name];
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      callback = _ref[_i];
      _results.push(callback(event.data));
    }
    return _results;
  };

  WebSocketRails.prototype.subscribe = function(channelName, successCallback, failureCallback) {
    var channel;
    if (this.channels[channelName] === null) {
      channel = new WebSocketRails.Channel(channelName, this, false, successCallback, failureCallback);
      this.channels[channelName] = channel;
      return channel;
    } else {
      return this.channels[channelName];
    }
  };

  WebSocketRails.prototype.subscribePrivate = function(channelName, successCallback, failureCallback) {
    var channel;
    if (this.channels[channelName] === null) {
      channel = new WebSocketRails.Channel(channelName, this, true, successCallback, failureCallback);
      this.channels[channelName] = channel;
      return channel;
    } else {
      return this.channels[channelName];
    }
  };

  WebSocketRails.prototype.unsubscribe = function(channelName) {
    if (this.channels[channelName] === null) {
      return;
    }
    this.channels[channelName].destroy();
    return delete this.channels[channelName];
  };

  WebSocketRails.prototype.dispatchChannel = function(event) {
    if (this.channels[event.channel] === null) {
      return;
    }
    return this.channels[event.channel].dispatch(event.name, event.data);
  };

  WebSocketRails.prototype.supportsWebsockets = function() {
    return typeof WebSocket === 'function' || typeof WebSocket === 'object';
  };

  WebSocketRails.prototype.connectionStale = function() {
    return this.state !== 'connected';
  };

  WebSocketRails.prototype.reconnectChannels = function() {
    var callbacks, channel, name, _ref, _results;
    _ref = this.channels;
    _results = [];
    for (name in _ref) {
      channel = _ref[name];
      callbacks = channel._callbacks;
      channel.destroy();
      delete this.channels[name];
      channel = channel.isPrivate ? this.subscribePrivate(name) : this.subscribe(name);
      channel._callbacks = callbacks;
      _results.push(channel);
    }
    return _results;
  };

  return WebSocketRails;

})();

WebSocketRails.AbstractConnection = require('./abstract_connection');
WebSocketRails.Channel = require('./channel');
WebSocketRails.Connection = require('./connection');
WebSocketRails.Event = require('./event');
WebSocketRails.HttpConnection = require('./http_connection');
__extends(WebSocketRails.HttpConnection, WebSocketRails.AbstractConnection);
WebSocketRails.WebSocketConnection = require('./websocket_connection');
__extends(WebSocketRails.WebSocketConnection, WebSocketRails.AbstractConnection);

module.exports = WebSocketRails;
<|endoftext|>


<commit_before>global.self = global

var WebSocketClient = require('websocket').client
var Paho = require('paho-mqtt')
require('dotenv').config()

global.WebSocket = function(wsurl, protocol) {
  var ws = new WebSocketClient()
  var connection
  var obj = {
    send: function(msg) {
      var nodeBuf = new Buffer(new Uint8Array(msg))
      connection.send(nodeBuf)
    },
    get readyState() {
      return ws.readyState;
    }
  };

  ws.binaryType = 'arraybuffer';

  ws.on("connect", function(conn) {
    connection = conn;
    conn.on("error", function(error) {
      console.log("socket error ", error);
      if (obj.onerror) {
        obj.onerror();
      }
    });

    conn.on("close", function(reasonCode, description) {
      console.log("socket closed ", description);
    })

    conn.on("message", function(message) {
      if (message.type === "binary") {
        if (obj.onmessage) {
          obj.onmessage({
            data: message.binaryData
          });
        }
      }
    });
    if (obj.onopen) {
      obj.onopen();
    }
  });
  ws.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
    if (obj.onerror) {
      obj.onerror(error);
    }
  });
  ws.connect(wsurl, protocol);
  return obj;
}

var LocalStorage = require('node-localstorage').LocalStorage
global.localStorage = new LocalStorage('./persistence')

var Paho = require('paho-mqtt')
global.Paho = Paho

function ensureValue(prop, value) {
  if (prop === null || prop === '' || prop[0] === '$') {
    return value
  }
  return prop
}

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1)
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4()
}

function printConfig(settings) {
  console.log(' - Eclipse Paho Javascript Client Test Harness Settings - ')
  console.log('Server URI: ' + settings.server + ':' + settings.port + settings.path)
  console.log('MQTT Version: ' + settings.mqttVersion)
  console.log('Interop Server URI: ' + settings.interopServer + ':' + settings.interopPort + settings.interopPath)
}

module.exports = {
  server: ensureValue(process.env.TEST_SERVER, 'localhost'),
  port: parseInt(ensureValue(process.env.TEST_SERVER_PORT, '443')),
  path: ensureValue(process.env.TEST_SERVER_PATH, '/ws'),
  mqttVersion: parseInt(ensureValue(process.env.TEST_SERVER_MQTTVER, '3')),
  interopServer: ensureValue(process.env.TEST_INTEROPSERVER, 'localhost'),
  interopPort: parseInt(ensureValue(process.env.TEST_INTEROPPORT, '443')),
  interopPath: ensureValue(process.env.TEST_INTEROPPATH, '/ws'),
  useSSL: ensureValue((process.env.TEST_USE_SSL === 'true'), true),
  topicPrefix: 'paho-mqtt-test-' + guid(),
  Paho: Paho,
  printConfig: printConfig
}<commit_msg>More javascript and tests.<commit_after>global.self = global

var WebSocketClient = require('websocket').client
var Paho = require('paho-mqtt')
require('dotenv').config()

global.WebSocket = function(wsurl, protocol) {
  var ws = new WebSocketClient()
  var connection
  var obj = {
    send: function(msg) {
      var nodeBuf = new Buffer(new Uint8Array(msg))
      connection.send(nodeBuf)
    },
    get readyState() {
      return ws.readyState;
    }
  };

  ws.binaryType = 'arraybuffer';

  ws.on("connect", function(conn) {
    connection = conn;
    conn.on("error", function(error) {
      console.log("socket error ", error);
      if (obj.onerror) {
        obj.onerror();
      }
    });

    conn.on("close", function(reasonCode, description) {
      console.log("socket closed ", description);
    })

    conn.on("message", function(message) {
      if (message.type === "binary") {
        if (obj.onmessage) {
          obj.onmessage({
            data: message.binaryData
          });
        }
      }
    });
    if (obj.onopen) {
      obj.onopen();
    }
  });
  ws.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
    if (obj.onerror) {
      obj.onerror(error);
    }
  });
  ws.connect(wsurl, protocol);
  return obj;
}

var LocalStorage = require('node-localstorage').LocalStorage
global.localStorage = new LocalStorage('./persistence')

var Paho = require('paho-mqtt')
global.Paho = Paho

function ensureValue(prop, value) {
  if (prop === null || prop === '') { // || prop[0] === '$') {
    return value
  }
  return prop
}

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1)
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4()
}

function printConfig(settings) {
  console.log(' - Eclipse Paho Javascript Client Test Harness Settings - ')
  console.log('Server URI: ' + settings.server + ':' + settings.port + settings.path)
  console.log('MQTT Version: ' + settings.mqttVersion)
  console.log('Interop Server URI: ' + settings.interopServer + ':' + settings.interopPort + settings.interopPath)
}

module.exports = {
  server: ensureValue(process.env.TEST_SERVER, 'localhost'),
  port: parseInt(ensureValue(process.env.TEST_SERVER_PORT, '443')),
  path: ensureValue(process.env.TEST_SERVER_PATH, '/ws'),
  mqttVersion: parseInt(ensureValue(process.env.TEST_SERVER_MQTTVER, '3')),
  interopServer: ensureValue(process.env.TEST_INTEROPSERVER, 'localhost'),
  interopPort: parseInt(ensureValue(process.env.TEST_INTEROPPORT, '443')),
  interopPath: ensureValue(process.env.TEST_INTEROPPATH, '/ws'),
  useSSL: ensureValue((process.env.TEST_USE_SSL === 'true'), true),
  topicPrefix: 'paho-mqtt-test-' + guid(),
  Paho: Paho,
  printConfig: printConfig
}<|endoftext|>


<commit_before>IONUX.Views.PlatformCommandFacepage = Backbone.View.extend({
  el: "#dynamic-container",
  template: _.template($("#instrument-command-facepage-tmpl").html()),

  events: {
    'click #start-instrument-agent-instance': 'start_agent',
    'click #stop-instrument-agent-instance': 'stop_agent',
    'click .issue_command': 'issue_command',
    'click .get_capabilities': 'get_capabilities'
  },

  initialize: function(){
    _.bindAll(this, "render", "start_agent" );
    this.model.bind("change", this.render);

    // console.log($('#start-instrument-agent-instance'));
  },

  render: function(){
    this.$el.empty().html(this.template(this.model.toJSON())).show();
    var agent_process_id = this.model.get('agent_instance')['agent_process_id'];
    if (agent_process_id) {
        $("#start-instrument-agent-instance").hide();
        $("#stop-instrument-agent-instance, .instrument-commands").show();
        this.get_capabilities();
    };

    $('#start-instrument-agent-instance').attr('value', 'Start Platform Agent');
    $('#stop-instrument-agent-instance').attr('value', 'Stop Platform Agent');
  },

  issue_command: function(evt){
    var button_elmt = $(evt.target);
    button_elmt.attr("disabled", "disabled");

    var select_elmt = this.$el.find('select');
    select_elmt.attr("disabled", "disabled");

    var selected_option = this.$el.find('option:selected');

    var command = selected_option.attr("value");
    var cap_type = selected_option.data('cap-type');
    if (cap_type) command += '?cap_type=' + cap_type;

    var self = this;

    $.ajax({
      url:command,
      dataType: 'json',
      success: function(resp) {
        var data = resp.data;
        $(".command-output").append($('
').html("OK: '" + command + "' was successful.
" + JSON.stringify(data.result)));
      },
      error: function() {
        $(".command-output").append($('
').text("ALERT: '" + command + "' was unsuccessful."));
      },
      complete: function(resp){
          button_elmt.removeAttr("disabled");
          select_elmt.removeAttr("disabled");
          self.get_capabilities();
      }
    });

    return false;
  },

  start_agent: function(evt) {
    var self = this;
    $.ajax({
        url: 'start/'+self.model.get('agent_instance')['_id']+'/',
        success: function() {
          $('.instrument-commands').show();
          $('#start-instrument-agent-instance').hide();
          $(' #stop-instrument-agent-instance').show();
          self.get_capabilities();
        },
        error: function() {
        }
    });
    return false;
  },

  get_capabilities: function(evt) {
      var self = this;
      $.ajax({
        url: 'get_capabilities?cap_type=abc123',
        dataType: 'json',
        success: function(resp){
            var agent_options = [];
            var resource_options = [];

            _.each(resp.data, function(option) {
                if (option.name != 'example'){
                    if (option.cap_type == 1) agent_options.push(option);
                    if (option.cap_type == 3) resource_options.push(option);
                };
            });

            var select_elmt = $('#new-commands');
            select_elmt.empty();

            var option_elmts = agent_options.concat(resource_options);
            var option_tmpl = '<option data-cap-type="<%= cap_type %>" value="<%= name %>"><%= name %></option>'
            _.each(option_elmts, function(option){
                select_elmt.append(_.template(option_tmpl, option));
            });
        },
        error: function(resp) {
            console.log('Error: ', resp);
        }
      });

  },

  stop_agent: function(evt) {
    var self = this;
    $.ajax({
      url: 'stop/'+self.model.get('agent_instance')['_id']+'/',
      success: function() {
        $('#stop-instrument-agent-instance').hide();
        $('#start-instrument-agent-instance').show();
        $('.instrument-commands').hide();
      },
      error: function() {
        alert("An error occured.");
      }
    });
    return false;
  }
});
<commit_msg>get_capabilites 'commands'.<commit_after>IONUX.Views.PlatformCommandFacepage = Backbone.View.extend({
  el: "#dynamic-container",
  template: _.template($("#instrument-command-facepage-tmpl").html()),

  events: {
    'click #start-instrument-agent-instance': 'start_agent',
    'click #stop-instrument-agent-instance': 'stop_agent',
    'click .issue_command': 'issue_command',
    'click .get_capabilities': 'get_capabilities'
  },

  initialize: function(){
    _.bindAll(this, "render", "start_agent" );
    this.model.bind("change", this.render);

    // console.log($('#start-instrument-agent-instance'));
  },

  render: function(){
    this.$el.empty().html(this.template(this.model.toJSON())).show();
    var agent_process_id = this.model.get('agent_instance')['agent_process_id'];
    if (agent_process_id) {
        $("#start-instrument-agent-instance").hide();
        $("#stop-instrument-agent-instance, .instrument-commands").show();
        this.get_capabilities();
    };

    $('#start-instrument-agent-instance').attr('value', 'Start Platform Agent');
    $('#stop-instrument-agent-instance').attr('value', 'Stop Platform Agent');
  },

  issue_command: function(evt){
    var button_elmt = $(evt.target);
    button_elmt.attr("disabled", "disabled");

    var select_elmt = this.$el.find('select');
    select_elmt.attr("disabled", "disabled");

    var selected_option = this.$el.find('option:selected');

    var command = selected_option.attr("value");
    var cap_type = selected_option.data('cap-type');
    if (cap_type) command += '?cap_type=' + cap_type;

    var self = this;

    $.ajax({
      url:command,
      dataType: 'json',
      success: function(resp) {
        var data = resp.data;
        $(".command-output").append($('
').html("OK: '" + command + "' was successful.
" + JSON.stringify(data.result)));
      },
      error: function() {
        $(".command-output").append($('
').text("ALERT: '" + command + "' was unsuccessful."));
      },
      complete: function(resp){
          button_elmt.removeAttr("disabled");
          select_elmt.removeAttr("disabled");
          self.get_capabilities();
      }
    });

    return false;
  },

  start_agent: function(evt) {
    var self = this;
    $.ajax({
        url: 'start/'+self.model.get('agent_instance')['_id']+'/',
        success: function() {
          $('.instrument-commands').show();
          $('#start-instrument-agent-instance').hide();
          $(' #stop-instrument-agent-instance').show();
          self.get_capabilities();
        },
        error: function() {
        }
    });
    return false;
  },

  get_capabilities: function(evt) {
      var self = this;
      $.ajax({
        url: 'get_capabilities?cap_type=abc123',
        dataType: 'json',
        success: function(resp){
            var agent_options = [];
            var resource_options = [];

            _.each(resp.data['commands'], function(option) {
                if (option.name != 'example'){
                    if (option.cap_type == 1) agent_options.push(option);
                    if (option.cap_type == 3) resource_options.push(option);
                };
            });

            var select_elmt = $('#new-commands');
            select_elmt.empty();

            var option_elmts = agent_options.concat(resource_options);
            var option_tmpl = '<option data-cap-type="<%= cap_type %>" value="<%= name %>"><%= name %></option>'
            _.each(option_elmts, function(option){
                select_elmt.append(_.template(option_tmpl, option));
            });
        },
        error: function(resp) {
            console.log('Error: ', resp);
        }
      });

  },

  stop_agent: function(evt) {
    var self = this;
    $.ajax({
      url: 'stop/'+self.model.get('agent_instance')['_id']+'/',
      success: function() {
        $('#stop-instrument-agent-instance').hide();
        $('#start-instrument-agent-instance').show();
        $('.instrument-commands').hide();
      },
      error: function() {
        alert("An error occured.");
      }
    });
    return false;
  }
});
<|endoftext|>


<commit_before>/*global Ext*/
/**
 * This version runs the index.html page in phantomjs and waits for just a timeout.
 *
 * Pro's - this will basically run the app, no need to override anything in Ext, will work
 *         with app.json
 * Con's - Due to the way phantomjs works all I can do is wait for the browser to timeout,
 *         ideally I'd like to be able to override Ext.application - launch event,
 *         but the techniques I've tried so far have been unsuccessful. A good solution
 *         would be to introduce a proxy server.
 */
var grunt        = require("grunt"),
    phantomjs    = require("grunt-lib-phantomjs").init(grunt),
    // Nodejs libs.
    path         = require("path"),
    fs           = require("fs"),
    // Get an asset file, local to the root of the project.
    asset        = path.join.bind(null, __dirname, ".."),
    sendMessageString = [""
    ].join("");

/**
 *
 * @param {string} appJsFilePath The path to the JS file which contains the Ext.application call - This path MUST be relative to th pageRoot
 * @param {string/Object} senchaDirOrAppJson The path to the Sencha framework directory OR the JSON from the app.json file for this project
 * @param {string} pageRoot The path to the directory which contains the main html page (usually index.html) relative to where this
 *                 task/grunt will be started
 * @param {boolean/string} isTouchOrPageToProcess If you set the Sencha framework dir then this should be true if you're using Sencha Touch.
 *                                 If you're using an app.json this will be the html page that should be used to process in phantomjs
 *                                 relative to the pageRoot
 * @param {boolean} pageToProcess The page that will be processed when looking for tags
 */
function PhantomJsHeadlessAnalyzer(appJsFilePath, senchaDirOrAppJson, pageRoot, pageToProcess) {
    this.appJsFilePath        = appJsFilePath;
    this.setPageRoot(pageRoot);
    this.pageToProcess        = pageToProcess;
    if (typeof senchaDirOrAppJson === "object") {
        // we're in mode where we use appJson
        this.appJson          = senchaDirOrAppJson;
    } else {
        if (senchaDirOrAppJson) {
            this.setSenchaDir(senchaDirOrAppJson);
        }
    }
}

PhantomJsHeadlessAnalyzer.prototype.setGrunt = function (gruntLive) {
    grunt = gruntLive;
};

function removeTrailingSlash(path) {
    return path[path.length - 1] === "/" ? path.substring(0, path.length - 1) : path;
}

PhantomJsHeadlessAnalyzer.prototype.setPageRoot = function (pageRoot) {
    this.pageRoot = pageRoot ? removeTrailingSlash(pageRoot) : ".";
};

function oneOfExistsInDir(dir, options) {
    for (var i = 0, len = options.length; i < len; i++) {
        if (fs.existsSync(dir + "/" + options[i])) {
            return true;
        }
    }
    return false;
}

PhantomJsHeadlessAnalyzer.prototype.setSenchaDir = function (_senchaDir) {
    this.senchaDir = _senchaDir;
    var resolvedDir = this.getSenchaFrameworkDir();
    var stats = fs.statSync(resolvedDir);

    if (stats.isDirectory()) {
        // if is dir - check for app.json
        if (oneOfExistsInDir(resolvedDir, ["sencha-touch.js", "sencha-touch-debug.js", "sencha-touch-all.js", "sencha-touch-all-debug.js"])) {
            this.isTouch = true;
        } else if (oneOfExistsInDir(resolvedDir, ["ext.js", "ext-debug.js", "ext-all.js", "ext-all-debug.js"])) {
            this.isTouch = false;
        } else {
            grunt.log.error("Could not find any of the expected Sencha Touch or Ext.js files in senchaDir " + resolvedDir);
        }
    } else {
        grunt.log.error("senchaDir property is not a directory " + resolvedDir);
    }
};

PhantomJsHeadlessAnalyzer.prototype.getSenchaFrameworkDir = function () {
    return path.normalize(this.pageRoot + "/" + this.senchaDir);
};

PhantomJsHeadlessAnalyzer.prototype.getSenchaCoreFile = function () {
    return path.normalize(this.pageRoot + "/" + this.senchaDir  + "/" + (this.isTouch ? "sencha-touch-debug.js" : "ext-debug.js"));
};

PhantomJsHeadlessAnalyzer.prototype.normaliseFilePaths = function (filePaths) {
    var output = [];
    for (var i = 0, len = filePaths.length; i < len; i++) {
        output.push(this.normaliseFilePath(filePaths[i]));
    }
    return output;
};

PhantomJsHeadlessAnalyzer.prototype.normaliseFilePath = function (filePath) {
    filePath = filePath.replace(/^file:(\/)*/, "/");
    if (!/^\//.test(filePath)) {
        filePath = this.pageRoot + "/" + filePath;
    }
    return path.normalize(this.pageRoot + "/" + path.relative(this.pageRoot, filePath));
};

PhantomJsHeadlessAnalyzer.prototype.reorderFiles = function (history) {
    var files = [],
        coreFile = this.getSenchaCoreFile(),
        appFile = path.normalize(this.pageRoot + "/" + this.appJsFilePath);
    files.push(coreFile);
    for (var i = 0, len = history.length; i < len; i++) {
        var filePath = history[i];//this.normaliseFilePath(history[i]);
        if (filePath !== appFile &&
                !/\/ext(-all|-all-debug|-debug){0,1}.js/.test(filePath) &&
                !/\/sencha-touch(-all|-all-debug|-debug){0,1}.js/.test(filePath) &&
                !/\/microloader\/development.js/.test(filePath)) {
            var stats   = fs.statSync(filePath);
            if (!stats.isDirectory()) {
                files.push(filePath);
            }
        }
    }
    files.push(appFile);
    return files;
};

PhantomJsHeadlessAnalyzer.prototype.setHtmlPageToProcess = function (tempPage) {
    if (this.pageToProcess) {
        // create the html page
        grunt.file.copy(this.pageRoot + "/" + this.pageToProcess, tempPage, {
            process: function (inputString) {
                // we need to inject the bridge
                return inputString.replace("", "" + sendMessageString);
            }
        });
    } else {
        // we'll dynamically create one
        var htmlString = ["",
            sendMessageString,
            "",
            "",
            ""].join("");
        grunt.file.write(tempPage, htmlString);
    }
    return tempPage;
};

function turnUrlIntoRelativeDirectory(relativeTo, url) {
    if (/^file:/.test(url)) {
        url = url.substring(5);
    }
    return path.relative(relativeTo, url.substring(0, url.lastIndexOf("/")));
}

PhantomJsHeadlessAnalyzer.prototype.resolveTheTwoFileSetsToBeInTheRightOrder = function (allScripts, history) {
    var i, len;
    // fix all paths to be normalised
    allScripts = this.normaliseFilePaths(allScripts);
    history = this.normaliseFilePaths(history);
    var startReplaceAfterThisItem = null;

    // 1) start iterating through allScripts and find the first file in the history list
    for (i = 0, len = allScripts.length; i < len; i++) {
        if (history.indexOf(allScripts[i]) > -1) {
            startReplaceAfterThisItem = allScripts[i - 1];
            break;
        }
    }
    // 2) now remove all the history files from allScripts
    for (i = 0, len = history.length; i < len; i++) {
        var indexToRemove = allScripts.indexOf(history[i]);
        if (indexToRemove > -1) {
            allScripts.splice(indexToRemove, 1);
        }
    }

    // 3) insert all the correctly ordered history files at the start point we found
    var notFound = true;
    i = 0;
    while (notFound && i < allScripts.length) {
        if (allScripts[i] === startReplaceAfterThisItem) {
            history.unshift(i, 0);
            allScripts.splice.apply(allScripts, history);
            notFound = false;
        }
        i++;
    }
    if (notFound) {
        grunt.log.error("An error occured whilst trying to calculate the dependencies");
    }
    return allScripts;
};

PhantomJsHeadlessAnalyzer.prototype.getDependencies = function (doneFn, task) {
    var me = this,
        errorCount = [],
        files = null,
        hasSeenSenchaLib = false,
        tempPage = this.pageRoot + "/" + Math.floor(Math.random() * 1000000) + ".html";

    function safeDeleteTempFile() {
        try {
            grunt.file["delete"](tempPage);
        } catch (e) {
            grunt.log.warn("An error occured whilst trying to delete the temporary file " + tempPage);
        }
    }

    phantomjs.on("onResourceRequested", function (response) {
        if (!hasSeenSenchaLib) {
            if (/\/ext(-all|-all-debug|-debug){0,1}.js/.test(response.url)) {
                me.setSenchaDir(turnUrlIntoRelativeDirectory(me.pageRoot, response.url));
                hasSeenSenchaLib = true;
            } else if (/\/sencha-touch(-all|-all-debug|-debug){0,1}.js/.test(response.url)) {
                me.setSenchaDir(turnUrlIntoRelativeDirectory(me.pageRoot, response.url));
                me.isTouch = true;
                hasSeenSenchaLib = true;
            }
        }
        if (/\.js/.test(response.url)) {
            grunt.log.debug(response.url);
        }
    });

    phantomjs.on("error.onError", function (msg, trace) {
        errorCount.push(msg);
        if (errorCount.length === 1) {
            grunt.log.warn("A JavaScript error occured whilst loading your page - this could" +
                            " cause problems with the generated file list. Run with -v to see all errors");
        }
        var msgStack = ["ERROR: " + msg];
        msgStack.push("TRACE:");
        trace.forEach(function (t) {
            msgStack.push(" -> " + t.file + ": " + t.line + (t["function"] ? " (in function \"" + t["function"] + "\")" : ""));
        });
        grunt.verbose.error(msgStack.join("\n"));
    });

    // Create some kind of "all done" event.
    phantomjs.on("mytask.done", function (foundFiles) {
        files = me.resolveTheTwoFileSetsToBeInTheRightOrder(foundFiles.scriptTags, foundFiles.history);
        phantomjs.halt();
    });

    // Built-in error handlers.
    phantomjs.on("fail.load", function (url) {
        safeDeleteTempFile();
        phantomjs.halt();
        grunt.warn("PhantomJS unable to load URL " + url);
    });

    phantomjs.on("fail.timeout", function () {
        safeDeleteTempFile();
        phantomjs.halt();
        grunt.warn("PhantomJS timed out.");
    });

    this.setHtmlPageToProcess(tempPage);

    // Spawn phantomjs
    phantomjs.spawn(tempPage, {
        // Additional PhantomJS options.
        options: {
            phantomScript: asset("phantomjs/main.js")
        },
        // Complete the task when done.
        done: function (err) {
            try {
                safeDeleteTempFile();
                doneFn(me.reorderFiles(
                    files
                ));
            } catch (e) {
                grunt.log.error(e);
                safeDeleteTempFile();
            }
        }
    });

};

module.exports = PhantomJsHeadlessAnalyzer;
<commit_msg>Don't try to stat files not on the local filesystem!<commit_after>/*global Ext*/
/**
 * This version runs the index.html page in phantomjs and waits for just a timeout.
 *
 * Pro's - this will basically run the app, no need to override anything in Ext, will work
 *         with app.json
 * Con's - Due to the way phantomjs works all I can do is wait for the browser to timeout,
 *         ideally I'd like to be able to override Ext.application - launch event,
 *         but the techniques I've tried so far have been unsuccessful. A good solution
 *         would be to introduce a proxy server.
 */
var grunt        = require("grunt"),
    phantomjs    = require("grunt-lib-phantomjs").init(grunt),
    // Nodejs libs.
    path         = require("path"),
    fs           = require("fs"),
    // Get an asset file, local to the root of the project.
    asset        = path.join.bind(null, __dirname, ".."),
    sendMessageString = [""
    ].join("");

/**
 *
 * @param {string} appJsFilePath The path to the JS file which contains the Ext.application call - This path MUST be relative to th pageRoot
 * @param {string/Object} senchaDirOrAppJson The path to the Sencha framework directory OR the JSON from the app.json file for this project
 * @param {string} pageRoot The path to the directory which contains the main html page (usually index.html) relative to where this
 *                 task/grunt will be started
 * @param {boolean/string} isTouchOrPageToProcess If you set the Sencha framework dir then this should be true if you're using Sencha Touch.
 *                                 If you're using an app.json this will be the html page that should be used to process in phantomjs
 *                                 relative to the pageRoot
 * @param {boolean} pageToProcess The page that will be processed when looking for tags
 */
function PhantomJsHeadlessAnalyzer(appJsFilePath, senchaDirOrAppJson, pageRoot, pageToProcess) {
    this.appJsFilePath        = appJsFilePath;
    this.setPageRoot(pageRoot);
    this.pageToProcess        = pageToProcess;
    if (typeof senchaDirOrAppJson === "object") {
        // we're in mode where we use appJson
        this.appJson          = senchaDirOrAppJson;
    } else {
        if (senchaDirOrAppJson) {
            this.setSenchaDir(senchaDirOrAppJson);
        }
    }
}

PhantomJsHeadlessAnalyzer.prototype.setGrunt = function (gruntLive) {
    grunt = gruntLive;
};

function removeTrailingSlash(path) {
    return path[path.length - 1] === "/" ? path.substring(0, path.length - 1) : path;
}

PhantomJsHeadlessAnalyzer.prototype.setPageRoot = function (pageRoot) {
    this.pageRoot = pageRoot ? removeTrailingSlash(pageRoot) : ".";
};

function oneOfExistsInDir(dir, options) {
    for (var i = 0, len = options.length; i < len; i++) {
        if (fs.existsSync(dir + "/" + options[i])) {
            return true;
        }
    }
    return false;
}

PhantomJsHeadlessAnalyzer.prototype.setSenchaDir = function (_senchaDir) {
    this.senchaDir = _senchaDir;
    var resolvedDir = this.getSenchaFrameworkDir();
    var stats = fs.statSync(resolvedDir);

    if (stats.isDirectory()) {
        // if is dir - check for app.json
        if (oneOfExistsInDir(resolvedDir, ["sencha-touch.js", "sencha-touch-debug.js", "sencha-touch-all.js", "sencha-touch-all-debug.js"])) {
            this.isTouch = true;
        } else if (oneOfExistsInDir(resolvedDir, ["ext.js", "ext-debug.js", "ext-all.js", "ext-all-debug.js"])) {
            this.isTouch = false;
        } else {
            grunt.log.error("Could not find any of the expected Sencha Touch or Ext.js files in senchaDir " + resolvedDir);
        }
    } else {
        grunt.log.error("senchaDir property is not a directory " + resolvedDir);
    }
};

PhantomJsHeadlessAnalyzer.prototype.getSenchaFrameworkDir = function () {
    return path.normalize(this.pageRoot + "/" + this.senchaDir);
};

PhantomJsHeadlessAnalyzer.prototype.getSenchaCoreFile = function () {
    return path.normalize(this.pageRoot + "/" + this.senchaDir  + "/" + (this.isTouch ? "sencha-touch-debug.js" : "ext-debug.js"));
};

PhantomJsHeadlessAnalyzer.prototype.normaliseFilePaths = function (filePaths) {
    var output = [];
    for (var i = 0, len = filePaths.length; i < len; i++) {
        output.push(this.normaliseFilePath(filePaths[i]));
    }
    return output;
};

PhantomJsHeadlessAnalyzer.prototype.normaliseFilePath = function (filePath) {
    filePath = filePath.replace(/^file:(\/)*/, "/");
    if (!/^\//.test(filePath)) {
        filePath = this.pageRoot + "/" + filePath;
    }
    return path.normalize(this.pageRoot + "/" + path.relative(this.pageRoot, filePath));
};

PhantomJsHeadlessAnalyzer.prototype.reorderFiles = function (history) {
    var files = [],
        coreFile = this.getSenchaCoreFile(),
        appFile = path.normalize(this.pageRoot + "/" + this.appJsFilePath);
    files.push(coreFile);
    for (var i = 0, len = history.length; i < len; i++) {
        var filePath = history[i];//this.normaliseFilePath(history[i]);
        if (filePath !== appFile &&
                !/\/ext(-all|-all-debug|-debug){0,1}.js/.test(filePath) &&
                !/\/sencha-touch(-all|-all-debug|-debug){0,1}.js/.test(filePath) &&
                !/\/microloader\/development.js/.test(filePath)) {

            if(fs.existsSync(filePath)) {

                var stats = fs.statSync(filePath);

                if (!stats.isDirectory()) {
                    files.push(filePath);
                }

            } else {
                grunt.log.warn('Excluding non filesystem based file ' + filePath);
            }
        }
    }
    files.push(appFile);
    return files;
};

PhantomJsHeadlessAnalyzer.prototype.setHtmlPageToProcess = function (tempPage) {
    if (this.pageToProcess) {
        // create the html page
        grunt.file.copy(this.pageRoot + "/" + this.pageToProcess, tempPage, {
            process: function (inputString) {
                // we need to inject the bridge
                return inputString.replace("", "" + sendMessageString);
            }
        });
    } else {
        // we'll dynamically create one
        var htmlString = ["",
            sendMessageString,
            "",
            "",
            ""].join("");
        grunt.file.write(tempPage, htmlString);
    }
    return tempPage;
};

function turnUrlIntoRelativeDirectory(relativeTo, url) {
    if (/^file:/.test(url)) {
        url = url.substring(5);
    }
    return path.relative(relativeTo, url.substring(0, url.lastIndexOf("/")));
}

PhantomJsHeadlessAnalyzer.prototype.resolveTheTwoFileSetsToBeInTheRightOrder = function (allScripts, history) {
    var i, len;
    // fix all paths to be normalised
    allScripts = this.normaliseFilePaths(allScripts);
    history = this.normaliseFilePaths(history);
    var startReplaceAfterThisItem = null;

    // 1) start iterating through allScripts and find the first file in the history list
    for (i = 0, len = allScripts.length; i < len; i++) {
        if (history.indexOf(allScripts[i]) > -1) {
            startReplaceAfterThisItem = allScripts[i - 1];
            break;
        }
    }
    // 2) now remove all the history files from allScripts
    for (i = 0, len = history.length; i < len; i++) {
        var indexToRemove = allScripts.indexOf(history[i]);
        if (indexToRemove > -1) {
            allScripts.splice(indexToRemove, 1);
        }
    }

    // 3) insert all the correctly ordered history files at the start point we found
    var notFound = true;
    i = 0;
    while (notFound && i < allScripts.length) {
        if (allScripts[i] === startReplaceAfterThisItem) {
            history.unshift(i, 0);
            allScripts.splice.apply(allScripts, history);
            notFound = false;
        }
        i++;
    }
    if (notFound) {
        grunt.log.error("An error occured whilst trying to calculate the dependencies");
    }
    return allScripts;
};

PhantomJsHeadlessAnalyzer.prototype.getDependencies = function (doneFn, task) {
    var me = this,
        errorCount = [],
        files = null,
        hasSeenSenchaLib = false,
        tempPage = this.pageRoot + "/" + Math.floor(Math.random() * 1000000) + ".html";

    function safeDeleteTempFile() {
        try {
            grunt.file["delete"](tempPage);
        } catch (e) {
            grunt.log.warn("An error occured whilst trying to delete the temporary file " + tempPage);
        }
    }

    phantomjs.on("onResourceRequested", function (response) {
        if (!hasSeenSenchaLib) {
            if (/\/ext(-all|-all-debug|-debug){0,1}.js/.test(response.url)) {
                me.setSenchaDir(turnUrlIntoRelativeDirectory(me.pageRoot, response.url));
                hasSeenSenchaLib = true;
            } else if (/\/sencha-touch(-all|-all-debug|-debug){0,1}.js/.test(response.url)) {
                me.setSenchaDir(turnUrlIntoRelativeDirectory(me.pageRoot, response.url));
                me.isTouch = true;
                hasSeenSenchaLib = true;
            }
        }
        if (/\.js/.test(response.url)) {
            grunt.log.debug(response.url);
        }
    });

    phantomjs.on("error.onError", function (msg, trace) {
        errorCount.push(msg);
        if (errorCount.length === 1) {
            grunt.log.warn("A JavaScript error occured whilst loading your page - this could" +
                            " cause problems with the generated file list. Run with -v to see all errors");
        }
        var msgStack = ["ERROR: " + msg];
        msgStack.push("TRACE:");
        trace.forEach(function (t) {
            msgStack.push(" -> " + t.file + ": " + t.line + (t["function"] ? " (in function \"" + t["function"] + "\")" : ""));
        });
        grunt.verbose.error(msgStack.join("\n"));
    });

    // Create some kind of "all done" event.
    phantomjs.on("mytask.done", function (foundFiles) {
        files = me.resolveTheTwoFileSetsToBeInTheRightOrder(foundFiles.scriptTags, foundFiles.history);
        phantomjs.halt();
    });

    // Built-in error handlers.
    phantomjs.on("fail.load", function (url) {
        safeDeleteTempFile();
        phantomjs.halt();
        grunt.warn("PhantomJS unable to load URL " + url);
    });

    phantomjs.on("fail.timeout", function () {
        safeDeleteTempFile();
        phantomjs.halt();
        grunt.warn("PhantomJS timed out.");
    });

    this.setHtmlPageToProcess(tempPage);

    // Spawn phantomjs
    phantomjs.spawn(tempPage, {
        // Additional PhantomJS options.
        options: {
            phantomScript: asset("phantomjs/main.js")
        },
        // Complete the task when done.
        done: function (err) {
            try {
                safeDeleteTempFile();
                doneFn(me.reorderFiles(
                    files
                ));
            } catch (e) {
                grunt.log.error(e);
                safeDeleteTempFile();
            }
        }
    });

};

module.exports = PhantomJsHeadlessAnalyzer;
<|endoftext|>


<commit_before>/**
 * 500 (Server Error) Handler
 *
 * Usage:
 * return res.serverError(err);
 *
 * @param {Array|Object|String|Error} error(s)     [optional]
 *
 * NOTE:
 * If something throws in a policy or controller, or an internal
 * error is encountered, Sails will call `res.serverError()`.
 */

module.exports = function serverError (errors) {

  // Get access to `req`, `res`, `sails`
  var req = this.req;
  var res = this.res;
  var sails = req._sails;

  var viewFilePath = '500',
    statusCode = 500,
    i, errorToLog, errorToJSON;

  var result = {
    status: statusCode
  };

  // Normalize a {String|Object|Error} or array of {String|Object|Error}
  // into an array of proper, readable {Error}
  var errorsToDisplay = sails.util.normalizeErrors(errors);
  for (i in errorsToDisplay) {

    // Log error(s) as clean `stack`
    // (avoids ending up with \n, etc.)
    if (errorsToDisplay[i].original) {
      errorToLog = sails.util.inspect(errorsToDisplay[i].original);
    } else {
      errorToLog = errorsToDisplay[i].stack;
    }
    sails.log.error('Server Error (500)');
    sails.log.error(errorToLog);

    // Use original error if it exists
    errorToJSON = errorsToDisplay[i].original || errorsToDisplay[i].message;
    errorsToDisplay[i] = errorToJSON;
  }

  // Only include errors if application environment is set to 'development'
  // In production, don't display any identifying information about the error(s)
  if (sails.config.environment === 'development') {
    result.errors = errorsToDisplay;
  }

  // Set status code
  res.status(result.status);

  // If the user-agent wants JSON, respond with JSON
  if (req.wantsJSON) {
    return res.json(result);
  }

  // Make data more readable for view locals
  var locals = _.mapValues(result, function readabilify(value) {
    if (sails.util.isArray(value)) {
      return _.map(value, readabilify);
    }
    else if (sails.util.isPlainObject(value)) {
      return sails.util.inspect(value);
    }
    else return value;
  });

  // And try to render view
  res.render(viewFilePath, locals, function(err) {
    // But if the view doesn't exist, or a rendering error occured, just send JSON
    if (err) return res.json(result);

    // Otherwise, if it can be rendered, the `views/500.*` page is rendered
    res.render(viewFilePath, locals);
  });
};
<commit_msg>Fix up boilerplate res.serverError()<commit_after>/**
 * 500 (Server Error) Handler
 *
 * Usage:
 * return res.serverError();
 * return res.serverError(err);
 * return res.serverError(err, view);
 * return res.serverError(err, redirectTo);
 *
 * @param {Array|Object|String|Error} err     [optional]
 *
 * NOTE:
 * If something throws in a policy or controller, or an internal
 * error is encountered, Sails will call `res.serverError()`
 * automatically.
 */

module.exports = function serverError (err, viewOrRedirect) {

  // Get access to `req` & `res`
  var req = this.req;
  var res = this.res;

  // Serve JSON (with optional JSONP support)
  function sendJSON (data) {
    if (!data) {
      return res.send();
    }
    else if ( req.options.jsonp && !req.isSocket ) {
      return res.jsonp(data);
    }
    else return res.json(data);
  }

  // Set status code
  res.status(500);

  // Log error to console
  this.req._sails.log.error('Server Error (500)');
  this.req._sails.log.error(err);

  // Only include errors in response if application environment
  // is not set to 'production'.  In production, we shouldn't
  // send back any identifying information about errors.
  if (this.req._sails.config.environment === 'production') {
    err = undefined;
  }

  // If the user-agent wants JSON, always respond with JSON
  if (req.wantsJSON || !viewOrRedirect) {
    return sendJSON(err);
  }

  // Serve HTML view or redirect to specified URL
  if (typeof viewOrRedirect === 'string') {
    if (viewOrRedirect.match(/^(\/|http:\/\/|https:\/\/)/)) {
      return res.redirect(viewOrRedirect);
    }
    else return res.view(viewOrRedirect, err, function viewDoesntExist() {
      return sendJSON(err);
    });
  }
  else return res.view('500', err, function viewDoesntExist() {
    return sendJSON(err);
  });
};
<|endoftext|>


<commit_before>'use strict';

process.env.NODE_ENV = 'test';

var request = require('../../helper/setup-supertest')('http://localhost:3001')
  , chai = require('../../helper/setup-chai')
  , status = require('../../../lib/server/status')
  , login = require('../../helper/login')(request)
  , logout = require('../../helper/logout')(request)
  , mongoInit = require('../../init/mongo-init')
  , commentInit = require('../../init/comments-init')
  ;

describe('Vote comment API', () => {

	before((done) => {
		mongoInit.connect().then(commentInit).catch(console.log).fin(done);
	});

	after((done) => {
		commentInit().then(mongoInit.disconnect).catch(console.log).fin(done);
	});

	describe('#voteComment', () => {
		var cid = '77ac6f7b9b0d0b0457673daf';

		it('should not allow anonymous users to vote', (done) => {
			request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'malicious text'})
				.end((err, res) => {
					// console.log('res: ');
					// console.log(JSON.stringify(res));
					// console.log('\n');
					// console.log('err: ');
					// console.log(err);
					res.body.status.should.be.equal(status.codes.UserAuthRequired.code);
					res.body.value.should.have.property('message');
					done();
				});
		});

		it('vote should not be empty', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: ''})
				.end((err, res) => {
					res.body.status.shoud.be.equal(status.codes.EmptyVote.code);
            		res.body.value.should.have.property('message');
				});
			logout().then(done);
			});
		});

		it('vote should be only up- or down-vote', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'lol'})
				.end((err, res) => {
					res.body.status.shoud.be.equal(status.codes.WrongVote.code);
            		res.body.value.should.have.property('message');
				});
			logout().then(done);
			});
		})

		it('should get right post to vote on and allow logged-in users to vote', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'upvote'})
				.end((err, res) => {
					res.body.status.shoud.be.equal(0);
            		res.body.value.should.exist();
            		request
            			.get('/api/v1/comments/' + cid)
            			.end((err, res) => {
            				expect(res.body.value).to.include.members({ votes: ['upvote'] });
            			});
				});
			logout().then(done);
			});
		});

		it('should only allow user to vote once', (done) => {
			done();
		});
	});

});<commit_msg>another addvote for comment test added, passing<commit_after>'use strict';

process.env.NODE_ENV = 'test';

var request = require('../../helper/setup-supertest')('http://localhost:3001')
  , chai = require('../../helper/setup-chai')
  , status = require('../../../lib/server/status')
  , login = require('../../helper/login')(request)
  , logout = require('../../helper/logout')(request)
  , mongoInit = require('../../init/mongo-init')
  , commentInit = require('../../init/comments-init')
  ;

describe('Vote comment API', () => {

	before((done) => {
		mongoInit.connect().then(commentInit).catch(console.log).fin(done);
	});

	after((done) => {
		commentInit().then(mongoInit.disconnect).catch(console.log).fin(done);
	});

	describe('#voteComment', () => {
		var cid = '77ac6f7b9b0d0b0457673daf';

		it('should not allow anonymous users to vote', (done) => {
			request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'malicious text'})
				.end((err, res) => {
					// console.log('res: ');
					// console.log(JSON.stringify(res));
					// console.log('\n');
					// console.log('err: ');
					// console.log(err);
					res.body.status.should.be.equal(status.codes.UserAuthRequired.code);
					res.body.value.should.have.property('message');
					done();
				});
		});

		it('vote should not be empty', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: ''})
				.end((err, res) => {
					res.body.status.shoud.be.equal(status.codes.EmptyVote.code);
            		res.body.value.should.have.property('message');
				});
			logout().then(done);
			});
		});

		it('vote should be only up- or down-vote', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'lol'})
				.end((err, res) => {
					res.body.status.shoud.be.equal(status.codes.WrongVote.code);
            		res.body.value.should.have.property('message');
				});
			logout().then(done);
			});
		})

		it('should get right post to vote on and allow logged-in users to vote', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'upvote'})
				.end((err, res) => {
					res.body.status.shoud.be.equal(0);
            		res.body.value.should.exist();
            		request
            			.get('/api/v1/comments/' + cid)
            			.end((err, res) => {
            				expect(res.body.value).to.include.members({ votes: ['upvote'] });
            			});
				});
			logout().then(done);
			});
		});

		it('should only allow user to vote once', (done) => {
			login('test@test.com', 'test').then(() => {
				request
				.post('/api/v1/comments/' + cid + '/votes')
				.send({type: 'upvote'})
				.end((err, res) => {
					request
					.post('/api/v1/comments/' + cid + '/votes')
					.send({type: 'downvote'})
					.end((err, res) => {
						res.body.status.shoud.be.equal(status.codes.AlreadyVoted.code);
            			res.body.value.should.have.property('message');
					});
				});
			logout().then(done);
			});
		});
	});

});<|endoftext|>