app-com
Version:
Pub Sub Library for Communication in your App
416 lines (331 loc) • 12.5 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.appCom = factory());
}(this, (function () { 'use strict';
var ERRORS = {
SPEARATOR_NOT_SET: 'Set separator first with .setSeparator().',
SPEARATOR_NO_STRING: 'Separator must be a string.',
SPEARATOR_LENGHT: 'Separator length should be 1 - wtf, are you doing?',
EVENTLIST_WRONG_FORMAT: 'Event list must be an array or object.',
EVENT_NAME_DUPLICATES: 'Duplicate event names.',
NO_EVENT_NAMES_FOUND: 'No event names registered.',
EVENT_NAME_NOT_REGISTERED: 'Event name must be registered before using it.',
EVENT_NAME_NOT_STRING: 'Event must be a string.',
EVENT_NAME_NO_SEPARATOR: 'Event must start with the separator char "{0}".',
EVENT_NAME_IS_WILDCARD: 'Event name can not be a wildcard. It can not end with "{0}".',
SUB_WAS_KILLED_BEFORE: 'Tried to call a method on killed subscription.',
SUB_WAS_STARTED_BEFORE: 'Subscription was stared before.',
SUB_WAS_STOPPED_BEFORE: 'Subscription was stopped before.',
EVENT_DATA_NOT_OBJECT: 'Event data must be an object.',
EVENT_CALLBACK_NOT_FUNCTION: 'Event callback must be a function.',
REGISTER_EMPTY: 'No events are registered. Register them before using the library!',
REGISTER_NOT_DYNAMIC: 'Do not change the event registry dynamically! Create a event hub an pass it at init of your app.',
SEPARATOR_NOT_DYNAMIC: 'Do not change the event separator dynamically! Create a event hub an pass the separator at init of your app.'
};
function replaceAll(search, replacement, target) {
return target.split(search).join(replacement);
}
function insert(target) {
var placeholderStart = '{',
placeholderEnd = '}';
for (var _len = arguments.length, replacements = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
replacements[_key - 1] = arguments[_key];
}
for (var _iterator = replacements.entries(), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _ref2 = _ref,
i = _ref2[0],
value = _ref2[1];
target = replaceAll(placeholderStart + i + placeholderEnd, value, target);
}
return target;
}
function inArray(needle, object, searchInKey) {
if (Object.prototype.toString.call(needle) === '[object Object]' || Object.prototype.toString.call(needle) === '[object Array]') {
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function (key) {
var value = object[key];
if (Object.prototype.toString.call(value) === '[object Object]' || Object.prototype.toString.call(value) === '[object Array]') {
value = JSON.stringify(value);
}
if (searchInKey) {
if (value === needle || key === needle) {
return true;
}
} else {
if (value === needle) {
return true;
}
}
});
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var Com$1 = (function () {
var separator = false,
registeredEventNames = [];
var subscriptions = {},
events = [];
return {
broadcast: broadcast,
subscribe: subscribe,
registerEventNames: registerEventNames,
setSeparator: setSeparator
};
/////////////////////////////
function registerEventNames(names) {
checkSeparator();
if (registeredEventNames.length > 0) {
throw new Error(ERRORS.REGISTER_NOT_DYNAMIC);
}
var namesFound = [];
if (isArray(names)) {
names.forEach(function (name) {
namesFound.push(name);
});
} else if (isObject(names)) {
namesFound = getAllPropertyValues(names);
} else {
throw new Error(ERRORS.EVENTLIST_WRONG_FORMAT);
}
var namesClean = cleanDuplicatesInArray(namesFound);
if (namesClean.length !== namesFound.length) {
throw new Error(ERRORS.EVENT_NAME_DUPLICATES);
}
if (namesClean.length === 0) {
throw new Error(ERRORS.NO_EVENT_NAMES_FOUND);
}
registeredEventNames = namesClean;
}
function setSeparator(sep) {
if (separator !== false) {
throw new Error(ERRORS.SEPARATOR_NOT_DYNAMIC);
}
if (!isString(sep)) {
throw new Error(ERRORS.SPEARATOR_NO_STRING);
}
if (sep.length !== 1) {
throw new Error(ERRORS.SPEARATOR_LENGHT);
}
separator = sep;
}
function subscribe(eventName, callback) {
checkForRegisteredEvents();
checkEventName(eventName);
if (!isFunction(callback)) {
throw new Error(ERRORS.EVENT_CALLBACK_NOT_FUNCTION);
}
var id = createUniqueIdFor(subscriptions);
subscriptions[id] = {
id: id, // unique id for the subscription
eventName: eventName, // path like representation as string
callback: callback, // callback
isActive: false, // for starting and stopping
isAlive: true // for killing
};
return {
kill: function kill() {
checkSubscription(id);
subscriptions[id].isAlive = false;
},
stop: function stop() {
checkSubscriptionForStopping(id);
subscriptions[id].isActive = false;
},
start: function start() {
checkSubscriptionForStarting(id);
subscriptions[id].isActive = true;
},
startWithLast: function startWithLast() {
checkSubscriptionForStarting(id);
subscriptions[id].isActive = true;
var match = getLastItem(getMatchingEvents(eventName));
if (match) {
callback(match.eventData, match);
}
},
startWithAll: function startWithAll() {
checkSubscriptionForStarting(id);
subscriptions[id].isActive = true;
var matches = getMatchingEvents(eventName);
matches.forEach(function (match) {
callback(match.eventData, match);
});
}
};
}
function broadcast(eventName) {
var eventData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
checkForRegisteredEvents();
checkEventNameForBroadcasting(eventName);
if (!isObject(eventData)) {
throw new Error(ERRORS.EVENT_DATA_NOT_OBJECT);
}
var event = {
timestamp: Date.now(),
eventName: eventName,
eventData: eventData
};
events.push(event);
Object.keys(subscriptions).forEach(function (key) {
var subscription = subscriptions[key];
if (subscription.isActive && subscription.isAlive) {
if (isCatchAllEvent(subscription.eventName)) {
subscription.callback(event.eventData, event);
} else if (isWildcardEvent(subscription.eventName)) {
if (isWildcardEventMatching(subscription.eventName, event.eventName)) {
subscription.callback(event.eventData, event);
}
} else if (subscription.eventName === event.eventName) {
subscription.callback(event.eventData, event);
}
}
});
}
function checkSeparator() {
if (separator === false) {
throw new Error(ERRORS.SPEARATOR_NOT_SET);
}
}
function checkForRegisteredEvents() {
checkSeparator();
if (registeredEventNames.length === 0) {
throw new Error(ERRORS.REGISTER_EMPTY);
}
}
function checkEventName(eventName) {
if (!isString(eventName)) {
throw new Error(ERRORS.EVENT_NAME_NOT_STRING);
}
if (!startsWithSeparator(eventName)) {
throw new Error(insert(ERRORS.EVENT_NAME_NO_SEPARATOR, separator));
}
if (!isRegistered(eventName)) {
throw new Error(ERRORS.EVENT_NAME_NOT_REGISTERED);
}
}
function checkEventNameForBroadcasting(eventName) {
checkEventName(eventName);
if (isCatchAllEvent(eventName) || isWildcardEvent(eventName)) {
throw new Error(ERRORS.EVENT_NAME_IS_WILDCARD);
}
}
function getMatchingEvents(eventName) {
var matches = [];
if (isCatchAllEvent(eventName)) {
matches = events;
} else if (isWildcardEvent(eventName)) {
events.some(function (e) {
if (isWildcardEventMatching(eventName, e.eventName)) {
matches.push(e);
}
});
} else {
events.some(function (e) {
if (eventName === e.eventName) {
matches.push(e);
}
});
}
return matches;
}
function isRegistered(eventName) {
return inArray(eventName, registeredEventNames);
}
function startsWithSeparator(something) {
return something.charAt(0) === separator;
}
function isCatchAllEvent(eventName) {
return eventName === separator;
}
function isWildcardEvent(eventName) {
return eventName.slice(-1) === separator;
}
function isWildcardEventMatching(wildcardEventName, eventName) {
return eventName.substring(0, wildcardEventName.length) === wildcardEventName;
}
function getLastItem(arr) {
if (typeof arr[arr.length - 1] !== 'undefined') {
return arr[arr.length - 1];
} else {
return false;
}
}
function checkSubscription(id) {
if (typeof subscriptions[id] === 'undefined' || !subscriptions[id].isAlive) {
throw new Error(ERRORS.SUB_WAS_KILLED_BEFORE);
}
}
function checkSubscriptionForStarting(id) {
checkSubscription(id);
if (subscriptions[id].isActive === true) {
throw new Error(ERRORS.SUB_WAS_STARTED_BEFORE);
}
}
function checkSubscriptionForStopping(id) {
checkSubscription(id);
if (subscriptions[id].isActive === false) {
throw new Error(ERRORS.SUB_WAS_STOPPED_BEFORE);
}
}
});
/////////////
function createUniqueIdFor(variable) {
var id = void 0;
while (!id || typeof variable[id] !== 'undefined') {
id = Math.random().toString(36).substr(2, 9);
}
return id;
}
function isFunction(something) {
return something && typeof something === 'function';
}
function isString(something) {
return typeof something === 'string';
}
function isArray(obj) {
return obj && Array.isArray(obj);
}
function isObject(data) {
return data && (typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object' && !Array.isArray(data);
}
function getAllPropertyValues() {
var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var values = [];
Object.keys(obj).forEach(function (key) {
if (isObject(obj[key])) {
getAllPropertyValues(obj[key]).forEach(function (v) {
values.push(v);
});
} else {
values.push(obj[key]);
}
});
return values;
}
function cleanDuplicatesInArray(arr) {
var i = void 0,
len = arr.length,
out = [],
obj = {};
for (i = 0; i < len; i++) {
obj[arr[i]] = 0;
}
for (i in obj) {
if (obj.hasOwnProperty(i)) {
out.push(i);
}
}
return out;
}
return Com$1;
})));