cross-domain-emitter
Version:
a cross domain or carrier event emittier
1,192 lines (1,164 loc) • 55.6 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CrossDomainEmitter = {}));
})(this, (function (exports) { 'use strict';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var BaseTransceiver = /** @class */ (function () {
function BaseTransceiver() {
}
return BaseTransceiver;
}());
var Signal = /** @class */ (function () {
function Signal(uuid, name, data, option) {
this.uuid = "";
this.name = "";
this.data = null;
this.uuid = uuid;
this.name = name;
this.data = data;
this.timestamp = Date.now();
if (option) {
this.option = option;
}
}
Signal.prototype.serialize = function () {
return JSON.stringify(this);
};
Signal.deserialize = function (serializeStr) {
if (serializeStr) {
try {
var data = JSON.parse(serializeStr);
var signal = new Signal(data.uuid, data.name, data.data, data.option);
signal.timestamp = data.timestamp;
return signal;
}
catch (error) {
console.log(error);
return new Signal("", "unknown", serializeStr);
}
}
else {
return new Signal("", "unknown");
}
};
Signal.copyFrom = function (data) {
return new Signal(data.uuid, data.name, data.data, data.option);
};
return Signal;
}());
function isObject(obj) {
return Object.prototype.toString.call(obj) == "[object Object]";
}
function isArray(obj) {
return Object.prototype.toString.call(obj) == "[object Array]";
}
function isString(obj) {
return Object.prototype.toString.call(obj) == "[object String]";
}
function isFunction(obj) {
return Object.prototype.toString.call(obj) == "[object Function]";
}
/**
*
* 判断是否为空
* @export
* @param {*} obj
* @return {*} {boolean}
*/
function isEmpty(obj) {
return obj === undefined || obj === null || obj === "";
}
function walkArray(array, handler, context) {
if (isEmpty(array)) {
return;
}
var len = array.length;
var value;
for (var i = 0; i < len; i++) {
value = array[i];
if (!isEmpty(handler)) {
var stop_2 = handler.call(context, value, i, array);
if (stop_2) {
return;
}
}
}
}
function getQueryByUrl(url) {
var query = {};
var queryStr = url.split("?")[1];
if (queryStr) {
var vars = queryStr.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
query[pair[0]] = pair[1];
}
}
return query;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var dist = {exports: {}};
(function (module, exports) {
!function(t,e){module.exports=e();}(commonjsGlobal,(function(){ /*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */function t(t,e,n){if(n||2===arguments.length)for(var r,o=0,i=e.length;o<i;o++)!r&&o in e||(r||(r=Array.prototype.slice.call(e,0,o)),r[o]=e[o]);return t.concat(r||Array.prototype.slice.call(e))}function e(t){return "[object Number]"==Object.prototype.toString.call(t)}function n(t){return "[object Object]"==Object.prototype.toString.call(t)}function r(t){return "[object Array]"==Object.prototype.toString.call(t)}function o(t){return null==t}function i(t,e,s,l){if(void 0===s&&(s=!1),void 0===l&&(l=!0),!l&&o(e))return t;if(r(c=e)||n(c)){if(n(e))for(var u in s&&(n(t)||(t={})),e)t[u]=i(t[u],e[u],!0,l);else if(r(e)){s&&(r(t)||(t=[]));for(var a=e.length,p=0;p<a;p++)t[p]=i(t[p],e[p],!0,l);}}else (l||o(t))&&(t=e);var c;return t}var s=function(){function t(t){this.name="",this.handlers=[],this.name=t;}return t.prototype.pushHandler=function(t,e,n){this.handlers.push({method:t,times:n,context:e});},t.prototype.deleHandler=function(t){var e=null;return this.walkHandlers((function(n,r,o){if(n.method===t)return e=o.splice(r,1),!0})),e},t.prototype.executeHandlers=function(t,n){void 0===t&&(t=!0),void 0===n&&(n=!1);for(var r=[],o=2;o<arguments.length;o++)r[o-2]=arguments[o];for(var s=this.handlers,l=null,u=0;u<s.length;u++){l=s[u];var a=void 0,p=void 0;if(a=n?i([],r):r,e(l.times)?(l.times>0&&(p=l.method.apply(l.context,a),l.times--),l.times<=0&&(s.splice(u,1),u--)):p=l.method.apply(l.context,a),p&&t)break}},t.prototype.walkHandlers=function(t){!function(t,e,n){if(!o(t))for(var r,i=t.length,s=0;s<i;s++)if(r=t[s],!o(e)&&e.call(n,r,s,t))return}(this.handlers,(function(e,n,r){return t(e,n,r)}));},t}(),l=function(){function n(){this.events={},this.trigger=this.emit;}return n.prototype.on=function(t,n,o,i){e(o)&&(o=i=o);for(var l,u=r(t)?t:(l=t,l?l.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g,""):l).split(/\s+/),a=this.events,p=u.length,c=0;c<p;c++){var f=u[c];a[f]||(a[f]=new s(f)),a[f].pushHandler(n,o,i);}return this},n.prototype.once=function(t,e,n){return this.on(t,e,1,n)},n.prototype.emit=function(e){for(var n,r=[],o=1;o<arguments.length;o++)r[o-1]=arguments[o];return this.events[e]&&(n=this.events[e]).executeHandlers.apply(n,t([!0,!1],r,!1)),this},n.prototype.emitOneCopy=function(e){for(var n,r=[],o=1;o<arguments.length;o++)r[o-1]=arguments[o];return this.events[e]&&(n=this.events[e]).executeHandlers.apply(n,t([!0,!0],r,!1)),this},n.prototype.broadCast=function(e){for(var n,r=[],o=1;o<arguments.length;o++)r[o-1]=arguments[o];return this.events[e]&&(n=this.events[e]).executeHandlers.apply(n,t([!1,!1],r,!1)),this},n.prototype.broadCastOneCopy=function(e){for(var n,r=[],o=1;o<arguments.length;o++)r[o-1]=arguments[o];return this.events[e]&&(n=this.events[e]).executeHandlers.apply(n,t([!1,!0],r,!1)),this},n.prototype.off=function(t,e){return this.events[t]&&(e?this.events[t].deleHandler(e):delete this.events[t]),this},n.prototype.clear=function(){return this.events={},this},n}();return l}));
} (dist));
var EventEmitter = dist.exports;
let nanoid$1 = (size = 21) =>
crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
byte &= 63;
if (byte < 36) {
id += byte.toString(36);
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase();
} else if (byte > 62) {
id += '-';
} else {
id += '_';
}
return id
}, '');
function nanoid(size) {
if (size === void 0) { size = 21; }
return nanoid$1(size);
}
function hingeJointTransceiver(transceiver, transceiverHandler) {
transceiver.addHandler(transceiverHandler);
transceiverHandler.addTransceiver(transceiver);
}
function unHingeJointTransceiver(transceiver, transceiverHandler) {
transceiver.removeHandler(transceiverHandler);
transceiverHandler.removeTransceiver(transceiver);
}
var EventBus = /** @class */ (function (_super) {
__extends(EventBus, _super);
function EventBus() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.id = nanoid();
_this.transceivers = [];
_this.emitters = [];
return _this;
}
EventBus.prototype.emit = function (eventName, data, option, transceivers) {
if (!option) {
option = {};
}
if (!option.emitterId) {
option.emitterId = this.id;
}
if (!option || option.local === true) {
_super.prototype.emit.call(this, eventName, data, option);
return this;
}
if (!option || option.local !== false) {
_super.prototype.emit.call(this, eventName, data, option);
}
if (transceivers) {
if (isArray(transceivers)) {
walkArray(transceivers, function (handler) {
if (handler instanceof BaseTransceiver) {
if (handler && handler.checkStatus()) {
handler.send(eventName, data, option);
}
}
else if (handler instanceof EventBus) {
handler.onMessage({
data: data,
name: eventName,
option: option,
});
}
});
}
else {
if (transceivers instanceof BaseTransceiver) {
if (transceivers.checkStatus()) {
transceivers.send(eventName, data, option);
}
}
else if (transceivers instanceof EventBus) {
transceivers.onMessage({
data: data,
name: eventName,
option: option,
});
}
}
return this;
}
this.emitters.forEach(function (emitter) {
emitter.onMessage({ data: data, name: eventName, option: option });
});
var defaultTransceivers = this.transceivers;
for (var i = 0; i < defaultTransceivers.length; i++) {
var handler = defaultTransceivers[i];
if (handler && handler.checkStatus()) {
handler.send(eventName, data, option);
}
else {
if (handler && handler.stop) {
handler.stop();
}
defaultTransceivers.splice(i, 1);
i--;
}
}
return this;
};
EventBus.prototype.bindTransceiver = function (transceiver) {
hingeJointTransceiver(transceiver, this);
};
EventBus.prototype.addTransceiver = function (transceiver) {
var flag = true;
walkArray(this.transceivers, function (target) {
if (target === transceiver) {
flag = false;
return true;
}
});
if (flag) {
this.transceivers.push(transceiver);
}
};
EventBus.prototype.removeTransceiver = function (transceiver) {
var _this = this;
walkArray(this.transceivers, function (target, index) {
if (target === transceiver) {
_this.transceivers.splice(index, 1);
return true;
}
});
};
EventBus.prototype.unBindTransceiver = function (transceiver) {
unHingeJointTransceiver(transceiver, this);
};
EventBus.prototype.clearTransceiver = function () {
this.transceivers = [];
};
EventBus.prototype.onMessage = function (data) {
_super.prototype.emit.call(this, data.name, data.data, data.option);
};
EventBus.prototype.addEmitter = function (emiter) {
var flag = true;
walkArray(this.emitters, function (target) {
if (target === emiter) {
flag = false;
return true;
}
});
if (flag) {
this.emitters.push(emiter);
}
};
EventBus.prototype.removeEmitter = function (emiter) {
var _this = this;
walkArray(this.emitters, function (target, index) {
if (target === emiter) {
_this.emitters.splice(index, 1);
return true;
}
});
};
return EventBus;
}(EventEmitter));
/**
*
* 返回 模拟的 Broswer/Server 模式 的请求。
* 请求标识:eventName 即http请求中的请求路径
* set: 设置响应的处理函数(调用resolve 发送处理结果)/或固定的值
* get:发起请求 获取set 设置的数据
* on: 接收 set 主动推送的数据变化
* off: 停止接收set 主动推送的数据变化
* destroy: 销毁
* @param {EventBus} instance
* @param {string} eventName
* @returns
*/
function createVirtualService(instance, eventName) {
var reqEvent = eventName + "_req";
var updateEvent = eventName + "_update";
var lastData = null;
var returnEvents = new Set();
return {
get: function () {
return new Promise(function (resolve) {
var returnEvent = reqEvent + "_" + nanoid();
returnEvents.add(returnEvent);
instance.once(returnEvent, function (data) {
returnEvents.delete(returnEvent);
resolve(data);
});
instance.emit(reqEvent, null, { returnEvent: returnEvent });
});
},
set: function (callBack, clear) {
if (clear === void 0) { clear = true; }
if (clear) {
instance.off(reqEvent);
}
instance.on(reqEvent, function (data, option) {
var targetEvent = reqEvent;
if (option && option.returnEvent) {
targetEvent = option.returnEvent;
}
if (isFunction(callBack)) {
new Promise(function (resolve) {
callBack(data, option, resolve);
}).then(function (data) {
instance.emit(targetEvent, data);
});
}
else {
instance.emit(targetEvent, callBack);
}
});
if (isFunction(callBack)) {
callBack(undefined, undefined, function (data) {
instance.emit(updateEvent, { newVal: data, oldVal: lastData });
lastData = data;
});
}
else {
instance.emit(updateEvent, { newVal: callBack, oldVal: lastData });
lastData = callBack;
}
},
on: function (callBack) {
instance.on(updateEvent, callBack);
},
off: function (callBack) {
instance.off(updateEvent, callBack);
},
destroy: function () {
returnEvents.forEach(function (eventName) {
instance.off(eventName);
});
instance.off(reqEvent);
instance.off(updateEvent);
},
};
}
var Store = /** @class */ (function (_super) {
__extends(Store, _super);
function Store() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.store = {};
return _this;
}
Store.prototype.set = function (key, value) {
var oldVal = this.store[key];
this.store[key] = value;
this.emit(key, { newVal: value, oldVal: oldVal });
};
Store.prototype.get = function (key) {
return this.store[key];
};
return Store;
}(EventBus));
var Status$2;
(function (Status) {
Status[Status["close"] = 0] = "close";
Status[Status["open"] = 1] = "open";
})(Status$2 || (Status$2 = {}));
var LocalStorageTransceiver = /** @class */ (function (_super) {
__extends(LocalStorageTransceiver, _super);
function LocalStorageTransceiver(option) {
var _this = _super.call(this) || this;
_this.status = Status$2.close;
_this.handlers = [];
_this.context = window;
_this.keyPrefix = "";
_this.filter = undefined;
_this.uuid = "";
_this.context = option.win;
_this.filter = option.filter;
if (option.keyPrefix) {
_this.keyPrefix = option.keyPrefix;
}
_this.uuid = nanoid$1();
return _this;
}
LocalStorageTransceiver.prototype.isValidName = function (eventName) {
if (!this.keyPrefix || (eventName && eventName.indexOf(this.keyPrefix) === 0)) {
return true;
}
return false;
};
LocalStorageTransceiver.prototype.getRealName = function (name) {
return name.replace(this.keyPrefix, "");
};
LocalStorageTransceiver.prototype.messageHandler = function (event) {
var eventName = event.key;
var data = this.context.localStorage.getItem(eventName);
if (!data) {
return;
}
if (this.isValidName(eventName)) {
var realName = this.getRealName(eventName);
var signal_1 = Signal.deserialize(data);
signal_1.name = realName;
if (signal_1.uuid !== this.uuid) {
if (!this.filter || this.filter(event)) {
walkArray(this.handlers, function (handler) {
handler.onMessage(signal_1);
});
this.context.localStorage.removeItem(eventName);
}
}
}
};
LocalStorageTransceiver.prototype.send = function (eventName, data, option) {
var name = this.getEventName(eventName);
var str = new Signal(this.uuid, eventName, data, option).serialize();
this.context.localStorage.setItem(name, str);
return this;
};
LocalStorageTransceiver.prototype.getEventName = function (eventName) {
return this.keyPrefix + eventName;
};
LocalStorageTransceiver.prototype.start = function () {
if (this.status === Status$2.close) {
this.status = Status$2.open;
this.context.addEventListener("storage", this.messageHandler.bind(this));
}
};
LocalStorageTransceiver.prototype.stop = function () {
this.status = Status$2.close;
this.context.removeEventListener("storage", this.messageHandler.bind(this));
};
LocalStorageTransceiver.prototype.clearHandler = function () {
this.handlers = [];
};
LocalStorageTransceiver.prototype.addHandler = function (handler) {
var flag = true;
walkArray(this.handlers, function (target) {
if (target === handler) {
flag = false;
return true;
}
});
if (flag) {
this.handlers.push(handler);
}
};
LocalStorageTransceiver.prototype.removeHandler = function (handler) {
var _this = this;
walkArray(this.handlers, function (target, index) {
if (target === handler) {
_this.handlers.splice(index, 1);
return true;
}
});
};
LocalStorageTransceiver.prototype.checkStatus = function () {
return this.status === Status$2.open && !!this.context;
};
LocalStorageTransceiver.prototype.readHistoryMessage = function () {
var storage = this.context.localStorage;
for (var key in storage) {
var event_1 = new StorageEvent("history");
event_1.initStorageEvent(key);
this.messageHandler(event_1);
}
};
return LocalStorageTransceiver;
}(BaseTransceiver));
function createLocalStorageTransceiver(option) {
return new LocalStorageTransceiver(option);
}
/**
* 接收器状态
* 0 处于关闭状态,1处于打开状态,3 处于链接中状态,4:处于链接失败状态,只有处于打开状态才能可接收和发送数据
*
* @enum {number}
*/
var Status$1;
(function (Status) {
Status[Status["close"] = 0] = "close";
Status[Status["open"] = 1] = "open";
Status[Status["connecting"] = 3] = "connecting";
Status[Status["error"] = 4] = "error";
})(Status$1 || (Status$1 = {}));
var WindowTransceiver = /** @class */ (function (_super) {
__extends(WindowTransceiver, _super);
function WindowTransceiver(option) {
var _this = _super.call(this) || this;
_this.handlers = [];
_this.context = window;
_this.status = Status$1.close;
_this.host = "";
_this.allowHost = [];
_this.id = "";
_this.uuidKey = "";
_this.uuidValue = ""; // 用于通信认证
_this.maxRetryTimes = 3;
_this.retryTimes = -1;
_this.reconnectInterval = 500;
_this.timeOutId = null;
_this.connectError = undefined;
_this._messageHandlerWrap = null;
_this.connectedCall = [];
_this.context = option.win;
_this.host = option.host;
_this.allowHost = option.allowHost;
_this.id = option.idGenerator
? isFunction(option.idGenerator)
? option.idGenerator()
: option.idGenerator
: nanoid();
return _this;
}
WindowTransceiver.prototype.messageHandler = function (event) {
if (!this.checkStatus()) {
this.stop();
return;
}
if ((this.allowHost && this.allowHost.includes(event.origin)) ||
this.host === event.origin ||
this.host === "*") {
var signal_1 = null;
if (isString(event.data)) {
signal_1 = Signal.deserialize(event.data);
}
else if (isObject(event.data) && event.data.name) {
signal_1 = Signal.copyFrom(event.data);
}
if (isObject(signal_1) && signal_1.uuid === this.uuidValue) {
if (signal_1.name === "connect") {
this.send("connected");
return;
}
if (signal_1.name === "connected") {
this.connected();
return;
}
if (!signal_1.option) {
signal_1.option = {};
}
signal_1.option.event = event;
signal_1.option.transceiver = this;
walkArray(this.handlers, function (handler) {
handler.onMessage(signal_1);
});
}
}
};
WindowTransceiver.prototype.send = function (eventName, data, option) {
if (!this.uuidValue) {
this.connectError = new Error("uuidValue is empty.");
return this;
}
if (this.status === Status$1.close) {
return this;
}
if (window.structuredClone != undefined) {
this.context.postMessage(new Signal(this.uuidValue, eventName, data, option), this.host);
}
else {
this.context.postMessage(new Signal(this.uuidValue, eventName, data, __assign(__assign({}, option), { transceiver: undefined, event: undefined })).serialize(), this.host);
}
return this;
};
WindowTransceiver.prototype.start = function () {
if (this.status === Status$1.close || this.status === Status$1.error) {
this.status = Status$1.connecting;
this._messageHandlerWrap = this.messageHandler.bind(this);
window.addEventListener("message", this._messageHandlerWrap, false);
this.connect();
}
};
WindowTransceiver.prototype.stop = function () {
this.status = Status$1.close;
this.resetProperties();
if (this._messageHandlerWrap) {
window.removeEventListener("message", this._messageHandlerWrap, false);
}
};
WindowTransceiver.prototype.clearHandler = function () {
this.handlers = [];
};
WindowTransceiver.prototype.addHandler = function (handler) {
var flag = true;
walkArray(this.handlers, function (target) {
if (target === handler) {
flag = false;
return true;
}
});
if (flag) {
this.handlers.push(handler);
}
};
WindowTransceiver.prototype.removeHandler = function (handler) {
var _this = this;
walkArray(this.handlers, function (target, index) {
if (target === handler) {
_this.handlers.splice(index, 1);
return true;
}
});
};
WindowTransceiver.prototype.checkStatus = function () {
if (this.context && this.context.parent) {
return true;
}
return false;
};
WindowTransceiver.prototype.setUUID = function (str) {
this.uuidValue = str;
};
WindowTransceiver.prototype.getUUID = function () {
return this.uuidValue;
};
WindowTransceiver.prototype.setUUIDKey = function (str) {
this.uuidKey = str;
};
WindowTransceiver.prototype.getUUIDKey = function () {
return this.uuidKey;
};
WindowTransceiver.prototype.changeOption = function (option) {
this.context = option.win;
this.host = option.host;
this.allowHost = option.allowHost;
};
WindowTransceiver.prototype.connect = function () {
var _this = this;
if (this.retryTimes <= this.maxRetryTimes) {
this.retryTimes++;
this.send("connect");
this.timeOutId = setTimeout(function () {
_this.connect();
}, this.reconnectInterval);
}
else {
this.connectError = new Error("connection retry fail.");
this.connectedFailure();
}
};
WindowTransceiver.prototype.connected = function () {
this.resetProperties();
this.status = Status$1.open;
this.excuteConnectedCall();
};
WindowTransceiver.prototype.excuteConnectedCall = function (error) {
while (this.connectedCall.length > 0) {
var handler = this.connectedCall.shift();
if (handler) {
handler(error);
}
}
};
WindowTransceiver.prototype.connectedFailure = function () {
this.status = Status$1.error;
this.excuteConnectedCall(this.connectError);
this.resetProperties();
};
WindowTransceiver.prototype.onConnected = function (callBack) {
switch (this.status) {
case Status$1.open:
callBack();
return;
case Status$1.error:
callBack(this.connectError);
return;
default:
this.connectedCall.push(callBack);
}
};
WindowTransceiver.prototype.resetProperties = function () {
this.retryTimes = -1;
if (this.timeOutId) {
clearTimeout(this.timeOutId);
this.timeOutId = null;
}
};
return WindowTransceiver;
}(BaseTransceiver));
function createWindowTransceiver(option) {
return new WindowTransceiver(option);
}
var WindowEventBus = /** @class */ (function (_super) {
__extends(WindowEventBus, _super);
function WindowEventBus(uuidKey) {
var _this = _super.call(this) || this;
_this.uuidKey = "";
_this.store = new Store();
_this.windowTransceivers = new Map();
_this.uuidKey = uuidKey;
return _this;
}
WindowEventBus.prototype.addWindowTransceiver = function (option) {
var transceiver = this.windowTransceivers.get(option.win);
if (transceiver) {
transceiver.changeOption(option);
}
else {
transceiver = createWindowTransceiver(option);
this.windowTransceivers.set(option.win, transceiver);
this.bindTransceiver(transceiver);
this.store.bindTransceiver(transceiver);
}
return transceiver;
};
WindowEventBus.prototype.removeWindowTransceiver = function (transceiver) {
transceiver.stop();
this.windowTransceivers.delete(transceiver.context);
this.unBindTransceiver(transceiver);
this.store.unBindTransceiver(transceiver);
};
WindowEventBus.prototype.removeWindowTransceiverByWindow = function (win) {
var transceiver = this.windowTransceivers.get(win);
if (transceiver) {
this.removeWindowTransceiver(transceiver);
}
};
WindowEventBus.prototype.findWindowTransceiverByWindowIds = function (ids) {
var _this = this;
var targets = [];
walkArray(ids, function (id) {
var target = _this.transceivers.find(function (transceiver) {
if (transceiver.id === id) {
return true;
}
});
if (target) {
targets.push(target);
}
});
return targets;
};
WindowEventBus.prototype.clearWindowTransceiver = function () {
var _this = this;
this.windowTransceivers.forEach(function (transceiver) {
_this.removeWindowTransceiver(transceiver);
});
};
return WindowEventBus;
}(EventBus));
var WindowClient = /** @class */ (function (_super) {
__extends(WindowClient, _super);
function WindowClient() {
return _super !== null && _super.apply(this, arguments) || this;
}
WindowClient.prototype.createIframeTransceiver = function (host) {
var uuid = this.getUUID(window.location.href);
var transceiver = this.addWindowTransceiver({
win: window.parent,
host: host,
});
transceiver.setUUID(uuid);
return transceiver;
};
WindowClient.prototype.getUUID = function (url) {
var query = getQueryByUrl(url);
return query[this.uuidKey];
};
return WindowClient;
}(WindowEventBus));
var WindowServer = /** @class */ (function (_super) {
__extends(WindowServer, _super);
function WindowServer() {
return _super !== null && _super.apply(this, arguments) || this;
}
WindowServer.prototype.addIframeTransceiver = function (option) {
var uuidValue = option.uuidValue ? option.uuidValue : nanoid();
var uuidKey = option.uuidKey ? option.uuidKey : this.uuidKey;
if (option.url) {
var url = this.addUUIDtoUrl(option.url, uuidKey, uuidValue);
option.iframe.src = url;
}
var transceiver = this.addWindowTransceiver(__assign({ win: option.iframe.contentWindow }, option));
transceiver.setUUID(uuidValue);
transceiver.setUUIDKey(uuidKey);
return transceiver;
};
WindowServer.prototype.changeIframeTransceiver = function (transceiver, option) {
var uuidValue = option.uuidValue ? option.uuidValue : transceiver.getUUID();
var uuidKey = option.uuidKey ? option.uuidKey : transceiver.getUUIDKey();
if (option.url) {
var url = this.addUUIDtoUrl(option.url, uuidKey, uuidValue);
option.iframe.src = url;
}
transceiver.changeOption({
win: option.iframe.contentWindow,
host: option.host,
allowHost: option.allowHost,
});
return transceiver;
};
WindowServer.prototype.removeIframeTransceiver = function (iframe) {
if (iframe.contentWindow) {
this.removeWindowTransceiverByWindow(iframe.contentWindow);
}
};
WindowServer.prototype.addUUIDtoUrl = function (url, uuidKey, uuidValue) {
if (url.indexOf("?") < 0) {
url = url + "?";
}
var uuidParmas = uuidKey + "=" + uuidValue;
if (/\?$/.test(url)) {
url = url + uuidParmas;
}
else {
url = url + "&" + uuidParmas;
}
return url;
};
return WindowServer;
}(WindowEventBus));
var Status;
(function (Status) {
Status[Status["close"] = 0] = "close";
Status[Status["open"] = 1] = "open";
})(Status || (Status = {}));
var BroadcastChannelTransceiver = /** @class */ (function (_super) {
__extends(BroadcastChannelTransceiver, _super);
function BroadcastChannelTransceiver(option) {
var _this = _super.call(this) || this;
_this.status = Status.close;
_this.handlers = [];
_this.filter = undefined;
_this.broadcastChannel = null;
_this.filter = option.filter;
_this.channelName = option.channelName || "cross-domain-emitter-broadcast-channel";
_this.uuid = nanoid();
// 创建BroadcastChannel
_this.broadcastChannel = new BroadcastChannel(_this.channelName);
return _this;
}
BroadcastChannelTransceiver.prototype.messageHandler = function (event) {
if (this.filter && !this.filter(event)) {
return;
}
try {
var data = event.data;
if (data && typeof data === "object" && data.uuid !== this.uuid) {
var signal_1 = new Signal(data.uuid, data.name, data.data, data.option);
signal_1.timestamp = data.timestamp;
walkArray(this.handlers, function (handler) {
handler.onMessage(signal_1);
});
}
}
catch (error) {
console.error("Failed to handle broadcast message:", error);
}
};
BroadcastChannelTransceiver.prototype.send = function (eventName, data, option) {
if (this.status !== Status.open || !this.broadcastChannel) {
return this;
}
var messageData = {
uuid: this.uuid,
name: eventName,
data: data,
option: option,
timestamp: Date.now(),
};
try {
this.broadcastChannel.postMessage(messageData);
}
catch (error) {
console.error("Failed to send message via BroadcastChannel:", error);
}
return this;
};
BroadcastChannelTransceiver.prototype.start = function () {
if (this.status === Status.close) {
if (!this.broadcastChannel) {
this.broadcastChannel = new BroadcastChannel(this.channelName);
}
this.status = Status.open;
// 设置消息处理器
this.broadcastChannel.onmessage = this.messageHandler.bind(this);
// 发送上线通知
this.send("__tab_connected", { tabId: this.uuid }, { local: true });
}
};
BroadcastChannelTransceiver.prototype.stop = function () {
if (this.status === Status.open) {
this.status = Status.close;
// 发送下线通知
this.send("__tab_disconnected", { tabId: this.uuid }, { local: true });
if (this.broadcastChannel) {
this.broadcastChannel.close();
this.broadcastChannel = null;
}
}
};
BroadcastChannelTransceiver.prototype.clearHandler = function () {
this.handlers = [];
};
BroadcastChannelTransceiver.prototype.addHandler = function (handler) {
var flag = true;
walkArray(this.handlers, function (target) {
if (target === handler) {
flag = false;
return true;
}
});
if (flag) {
this.handlers.push(handler);
}
};
BroadcastChannelTransceiver.prototype.removeHandler = function (handler) {
var _this = this;
walkArray(this.handlers, function (target, index) {
if (target === handler) {
_this.handlers.splice(index, 1);
return true;
}
});
};
BroadcastChannelTransceiver.prototype.checkStatus = function () {
return this.status === Status.open && !!this.broadcastChannel;
};
/**
* 检查BroadcastChannel是否可用
*/
BroadcastChannelTransceiver.isBroadcastChannelSupported = function () {
return typeof BroadcastChannel !== "undefined";
};
return BroadcastChannelTransceiver;
}(BaseTransceiver));
function createBroadcastChannelTransceiver(option) {
return new BroadcastChannelTransceiver(option);
}
exports.TransceiverType = void 0;
(function (TransceiverType) {
TransceiverType[TransceiverType["broadcastChannel"] = 0] = "broadcastChannel";
TransceiverType[TransceiverType["localStorage"] = 1] = "localStorage";
})(exports.TransceiverType || (exports.TransceiverType = {}));
var SameOriginTransceiver = /** @class */ (function () {
function SameOriginTransceiver(option) {
var _a;
// 通信方式
this.localStorageTransceiver = null;
this.broadcastChannelTransceiver = null;
this.currentTransceiver = null;
this.currentType = exports.TransceiverType.localStorage;
// 状态管理
this.isStarted = false;
this.handlers = [];
this.context = option.win || window;
this.filter = option.filter;
this.channelName = option.channelName || "cross-domain-emitter-same-origin";
this.keyPrefix = option.keyPrefix || "same-origin-";
this.uuid = nanoid();
this.preferBroadcastChannel = (_a = option.preferBroadcastChannel) !== null && _a !== void 0 ? _a : true;
this.initializeTransceivers();
}
SameOriginTransceiver.prototype.initializeTransceivers = function () {
// 优先创建BroadcastChannel(如果支持且优先)
if (SameOriginTransceiver.isBroadcastChannelSupported() && this.preferBroadcastChannel) {
this.broadcastChannelTransceiver = createBroadcastChannelTransceiver({
filter: this.filter,
channelName: this.channelName,
});
this.currentTransceiver = this.broadcastChannelTransceiver;
this.currentType = exports.TransceiverType.broadcastChannel;
return;
}
// 回退到localStorage
this.localStorageTransceiver = createLocalStorageTransceiver({
win: this.context,
filter: this.filter,
keyPrefix: this.keyPrefix,
});
this.currentTransceiver = this.localStorageTransceiver;
this.currentType = exports.TransceiverType.localStorage;
};
// 公共方法
SameOriginTransceiver.prototype.send = function (eventName, data, option) {
if (!this.isStarted || !this.currentTransceiver)
return this;
this.currentTransceiver.send(eventName, data, option);
return this;
};
SameOriginTransceiver.prototype.start = function () {
if (this.isStarted)
return this;
this.isStarted = true;
if (this.currentTransceiver) {
this.currentTransceiver.start();
}
return this;
};
SameOriginTransceiver.prototype.stop = function () {
if (!this.isStarted)
return this;
this.isStarted = false;
if (this.currentTransceiver) {
this.currentTransceiver.stop();
}
return this;
};
SameOriginTransceiver.prototype.restart = function () {
this.stop();
this.start();
return this;
};
// 处理器管理
SameOriginTransceiver.prototype.addHandler = function (handler) {
if (this.handlers.includes(handler))
return this;
this.handlers.push(handler);
if (this.currentTransceiver) {
this.currentTransceiver.addHandler(handler);
}
return this;
};
SameOriginTransceiver.prototype.removeHandler = function (handler) {
var index = this.handlers.indexOf(handler);
if (index > -1) {
this.handlers.splice(index, 1);
if (this.currentTransceiver) {
this.currentTransceiver.removeHandler(handler);
}
}
return this;
};
SameOriginTransceiver.prototype.clearHandler = function () {
this.handlers = [];
if (this.currentTransceiver) {
this.currentTransceiver.clearHandler();
}
return this;
};
// 状态查询
SameOriginTransceiver.prototype.checkStatus = function () {
var _a;
return this.isStarted && !!((_a = this.currentTransceiver) === null || _a === void 0 ? void 0 : _a.checkStatus());
};
SameOriginTransceiver.prototype.getCurrentTransceiverType = function () {
return this.currentType;
};
SameOriginTransceiver.isBroadcastChannelSupported = function () {
return BroadcastChannelTransceiver.isBroadcastChannelSupported();
};
// 通信方式切换
SameOriginTransceiver.prototype.switchToBroadcastChannel = function () {
if (!SameOriginTransceiver.isBroadcastChannelSupported())
return false;
// 如果已经是BroadcastChannel,无需切换
if (this.currentType === exports.TransceiverType.broadcastChannel)
return true;
// 创建BroadcastChannel收发器(如果不存在)
if (!this.broadcastChannelTransceiver) {
this.broadcastChannelTransceiver = createBroadcastChannelTransceiver({
filter: this.filter,
channelName: this.channelName,
});
}
// 切换收发器
this.switchTransceiver(this.broadcastChannelTransceiver, exports.TransceiverType.broadcastChannel);
return true;
};
SameOriginTransceiver.prototype.switchToLocalStorage = function () {
// 如果已经是localStorage,无需切换
if (this.currentType === exports.TransceiverType.localStorage)
return true;
// 创建localStorage收发器(如果不存在)
if (!this.localStorageTransceiver) {
this.localStorageTransceiver = createLocalStorageTransceiver({
win: this.context,
filter: this.filter,
keyPrefix: this.keyPrefix,
});
}
// 切换收发器
this.switchTransceiver(this.localStorageTransceiver, exports.TransceiverType.localStorage);
return true;
};
SameOriginTransceiver.prototype.switchTransceiver = function (newTransceiver, newType) {
// 停止当前收发器
if (this.currentTransceiver && this.isStarted) {
this.currentTransceiver.stop();
this.currentTransceiver.clearHandler();
}
// 切换到新收发器
this.currentTransceiver = newTransceiver;
this.currentType = newType;
// 重新添加所有处理器
this.handlers.forEach(function (handler) {
newTransceiver.addHandler(handler);
});
// 如果已启动,启动新收发器
if (this.isStarted) {
newTransceiver.start();
}
};
return SameOriginTransceiver;
}());
function createSameOriginTransceiver(option) {
return new SameOriginTransceiver(option);
}
var SameOriginEventBus = /** @class */ (function (_super) {
__extends(SameOriginEventBus, _super);
function SameOriginEventBus(option) {
if (option === void 0) { option = {}; }
var _this = _super.call(this) || this;
_this.channelName = option.channelName || "cross-domain-emitter-same-origin";
_this.keyPrefix = option.keyPrefix || "same-origin-";
// 创建SameOrigin收发器
_this.transceiver = createSameOriginTransceiver({
win: window,
filter: option.filter,
channelName: _this.channelName,
keyPrefix: _this.keyPrefix,
preferBroadcastChannel: option.preferBroadcastChannel,
});
// 绑定收发器
_this.bindTransceiver(_this.transceiver.currentTransceiver);
// 启动收发器
_this.transceiver.start();
return _this;
}
/**
* 发送消息到其他tab
* @param e