@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
178 lines (175 loc) • 5.38 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 1.0.1
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
import { Type } from '../../tools/type.mjs';
import { Text } from '../../tools/text.mjs';
import { omit } from '../../tools/index.mjs';
import { LoggerFactory } from '../../logger/logger-factory.mjs';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
class MessageManager {
static {
__name(this, "MessageManager");
}
#appFrame;
#callbackPromises;
#callbackSingletone;
_logger;
runCallbackHandler;
constructor(appFrame) {
this._logger = LoggerFactory.createNullLogger();
this.#appFrame = appFrame;
this.#callbackPromises = /* @__PURE__ */ new Map();
this.#callbackSingletone = /* @__PURE__ */ new Map();
this.runCallbackHandler = this._runCallback.bind(this);
}
setLogger(logger) {
this._logger = logger;
}
getLogger() {
return this._logger;
}
// region Events ////
/**
* Subscribe to the onMessage event of the parent window
*/
subscribe() {
window.addEventListener("message", this.runCallbackHandler);
}
/**
* Unsubscribe from the onMessage event of the parent window
*/
unsubscribe() {
window.removeEventListener("message", this.runCallbackHandler);
}
// endregion ////
/**
* Send message to parent window
* The answer (if) we will get in _runCallback
*
* @param command
* @param params
*/
async send(command, params = null) {
return new Promise((resolve, reject) => {
let cmd;
const promiseHandler = {
resolve,
reject,
timeoutId: null
};
const keyPromise = this.#setCallbackPromise(promiseHandler);
let paramsSend = null;
const optionsSend = omit(params || {}, ["singleOption", "callBack", "isSafely", "safelyTime"]);
const { callBack, singleOption } = params || {};
if (callBack) {
this.#callbackSingletone.set(keyPromise, callBack);
}
if (singleOption) {
paramsSend = singleOption;
} else if (Object.keys(optionsSend).length > 0) {
paramsSend = { ...optionsSend };
}
if (command.toString().includes(":")) {
cmd = {
method: command.toString(),
params: paramsSend || "",
callback: keyPromise,
appSid: this.#appFrame.getAppSid()
};
} else {
cmd = command.toString();
if (params?.isRawValue !== true && paramsSend) {
paramsSend = JSON.stringify(paramsSend);
} else if (params?.isRawValue === true && paramsSend && Type.isPlainObject(paramsSend) && paramsSend["value"]) {
paramsSend = paramsSend["value"];
}
const listParams = [
paramsSend || "",
keyPromise,
this.#appFrame.getAppSid()
];
cmd += ":" + listParams.filter(Boolean).join(":");
}
this.getLogger().debug(`send to ${this.#appFrame.getTargetOrigin()}`, {
cmd,
origin: this.#appFrame.getTargetOrigin()
});
parent.postMessage(cmd, this.#appFrame.getTargetOrigin());
if (params?.isSafely) {
const safelyTime = Number.parseInt(String(params?.safelyTime || 900));
this.#callbackPromises.get(keyPromise).timeoutId = window.setTimeout(
() => {
if (this.#callbackPromises.has(keyPromise)) {
this.getLogger().warning(`action ${command.toString()} stop by timeout`, {
command: command.toString(),
safelyTime
});
this.#callbackPromises.delete(keyPromise);
resolve({ isSafely: true });
}
},
safelyTime
);
}
});
}
/**
* Fulfilling a promise based on messages from the parent window
*
* @param event
* @private
*/
_runCallback(event) {
if (event.origin !== this.#appFrame.getTargetOrigin()) {
return;
}
if (event.data) {
this.getLogger().debug(`get from ${event.origin}`, {
data: event.data,
origin: event.origin
});
const tmp = event.data.split(":");
const cmd = {
id: tmp[0],
args: tmp.slice(1).join(":")
};
if (cmd.args) {
cmd.args = JSON.parse(cmd.args);
}
if (this.#callbackPromises.has(cmd.id)) {
const promise = this.#callbackPromises.get(cmd.id);
if (promise.timeoutId) {
clearTimeout(promise.timeoutId);
}
this.#callbackPromises.delete(cmd.id);
promise.resolve(cmd.args);
} else if (this.#callbackSingletone.has(cmd.id)) {
const callBack = this.#callbackSingletone.get(cmd.id);
if (callBack) {
callBack.apply(globalThis, [cmd.args]);
}
}
}
}
/**
* Storing a promise for a message from the parent window
*
* @param promiseHandler
* @private
*
* @memo We don't use Symbol here, because we need to pass it to the parent and then find and restore it.
*/
#setCallbackPromise(promiseHandler) {
const key = Text.getUniqId();
this.#callbackPromises.set(key, promiseHandler);
return key;
}
}
export { MessageManager };
//# sourceMappingURL=controller.mjs.map