@open-condo/bridge
Version:
A library that allows the client of your mini-application to communicate with the main user's client on different devices, using a common bridge API
230 lines (221 loc) • 7.37 kB
JavaScript
/******************************************************************************
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 */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
}
const DEFAULT_METHOD_TIMEOUTS = {
CondoWebAppRequestAuth: 10000, // 10 sec
};
const DEFAULT_TIMEOUT_MS = 1000; // 1 sec
function getNoResponseError(timeout) {
return {
errorType: 'client',
errorCode: 5,
errorReason: 'TIMEOUT_REACHED',
errorMessage: `Request was failed. Response was not received in ${timeout} ms timeout.`,
};
}
function* createCounter() {
let counter = 0;
while (true) {
yield counter++;
}
}
function createRequestResolver() {
const requestIdCounter = createCounter();
const controllers = {};
return {
add(controller, customId) {
const requestId = customId || requestIdCounter.next().value;
controllers[requestId] = controller;
return requestId;
},
resolve(requestId, data, isSuccess) {
const controller = controllers[requestId];
if (controller) {
if (isSuccess(data)) {
controller.resolve(data);
}
else {
controller.reject(data);
}
delete controllers[requestId];
}
},
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function promisifySend(send, subscribe) {
const requestResolver = createRequestResolver();
subscribe((event) => {
if (!event || !event.data || typeof event.data !== 'object') {
return;
}
if ('requestId' in event.data) {
const _a = event.data, { requestId } = _a, data = __rest(_a, ["requestId"]);
if (typeof requestId !== 'undefined') {
requestResolver.resolve(requestId, data, (data) => !('errorType' in data));
}
}
});
return function promisifiedSend(method, params = {}, timeout) {
const timeoutInMs = timeout || DEFAULT_METHOD_TIMEOUTS[method] || DEFAULT_TIMEOUT_MS;
return Promise.race([
new Promise((resolve, reject) => {
const requestId = requestResolver.add({ resolve, reject }, params.requestId);
send(method, Object.assign(Object.assign({}, params), { requestId }));
}),
new Promise((_, reject) => {
setTimeout(() => reject(getNoResponseError(timeoutInMs)), timeoutInMs);
}),
]);
};
}
var name = "@open-condo/bridge";
var description = "A library that allows the client of your mini-application to communicate with the main user's client on different devices, using a common bridge API ";
var keywords = [
"condo",
"open-condo-software",
"client",
"bridge"
];
var version = "2.3.0";
var repository = {
type: "git",
url: "git+https://github.com/open-condo-software/condo.git",
directory: "packages/bridge"
};
var author = {
name: "Matthew Savelev",
email: "matthew@doma.ai",
url: "https://github.com/SavelevMatthew"
};
var license = "MIT";
var files = [
"dist"
];
var main = "dist/index.js";
var module = "dist/index.es.js";
var browser = "dist/index.umd.js";
var types = "dist/types/src/index.d.ts";
var scripts = {
build: "rm -rf dist && NODE_ENV=production rollup -c",
watch: "rollup -c -w"
};
var publishConfig = {
access: "public"
};
var devDependencies = {
"@open-condo/tsconfig": "^1.0.4",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.0.0",
rollup: "^4.28.0",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-bundle-size": "^1.0.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
tslib: "^2.4.1",
typescript: "^5.8.3"
};
var pkg = {
name: name,
description: description,
keywords: keywords,
version: version,
repository: repository,
author: author,
license: license,
files: files,
main: main,
module: module,
browser: browser,
types: types,
scripts: scripts,
publishConfig: publishConfig,
devDependencies: devDependencies
};
const IS_CLIENT_SIDE = typeof window !== 'undefined';
// TODO(DOMA-5084): add mobile clients env checks
const IS_BROWSER_CLIENT = IS_CLIENT_SIDE;
const WEB_SPECIFIC_METHODS = [
'CondoWebAppCloseModalWindow',
'CondoWebAppGetActiveProgressBars',
'CondoWebAppGetFragment',
'CondoWebAppGetLaunchParams',
'CondoWebAppRedirect',
'CondoWebAppRequestAuth',
'CondoWebAppResizeWindow',
'CondoWebAppShowModalWindow',
'CondoWebAppShowNotification',
'CondoWebAppShowProgressBar',
'CondoWebAppUpdateModalWindow',
'CondoWebAppUpdateProgressBar',
];
const ALL_METHODS = [
...(IS_BROWSER_CLIENT ? WEB_SPECIFIC_METHODS : []),
];
const webBridge = IS_BROWSER_CLIENT
? parent
: undefined;
function createCondoBridge() {
const subscribers = [];
function send(method, params) {
if (webBridge && typeof webBridge.postMessage === 'function') {
// nosemgrep: javascript.browser.security.wildcard-postmessage-configuration.wildcard-postmessage-configuration
webBridge.postMessage({
handler: method,
params,
type: 'condo-bridge',
version: pkg.version,
}, '*');
}
}
function supports(method) {
return ALL_METHODS.includes(method);
}
function subscribe(listener) {
subscribers.push(listener);
}
function unsubscribe(listener) {
const idx = subscribers.indexOf(listener);
if (idx >= 0) {
subscribers.splice(idx, 1);
}
}
function handleResponseEvent(event) {
const response = event.data;
if (typeof response !== 'object') {
return;
}
subscribers.forEach(listener => listener(response));
}
if (IS_BROWSER_CLIENT && 'addEventListener' in window) {
window.addEventListener('message', handleResponseEvent);
}
return {
send: promisifySend(send, subscribe),
supports,
subscribe,
unsubscribe,
};
}
const bridge = createCondoBridge();
export { bridge as default };
//# sourceMappingURL=index.es.js.map