UNPKG

@corvina/corvina-app-connect

Version:

This library enables an application embedded as an iframe in Corvina to retrieve some information such as JWT, organization id, ...

603 lines (596 loc) 27.8 kB
(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.$corvina = {})); })(this, (function (exports) { 'use strict'; exports.MessageType = void 0; (function (MessageType) { MessageType["CORVINA_CONNECT_INIT"] = "CORVINA_CONNECT_INIT"; MessageType["CORVINA_CONNECT_INIT_RESPONSE"] = "CORVINA_CONNECT_INIT_RESPONSE"; MessageType["ORGANIZATION_ID_CHANGED"] = "ORGANIZATION_ID_CHANGED"; MessageType["ORGANIZATION_RESOURCE_ID_CHANGED"] = "ORGANIZATION_RESOURCE_ID_CHANGED"; MessageType["JWT_CHANGED"] = "JWT_CHANGED"; MessageType["USER_CHANGED"] = "USER_CHANGED"; MessageType["THEME_CHANGED"] = "THEME_CHANGED"; MessageType["CORVINA_NAVIGATE"] = "CORVINA_NAVIGATE"; MessageType["BRAND_NAME_CHANGED"] = "BRAND_NAME_CHANGED"; MessageType["IFRAME_HREF_CHANGED"] = "IFRAME_HREF_CHANGED"; MessageType["TRANSACTIONS_AUTHORIZATION_REQUEST"] = "TRANSACTIONS_AUTHORIZATION_REQUEST"; MessageType["TRANSACTIONS_AUTHORIZATION_RESPONSE"] = "TRANSACTIONS_AUTHORIZATION_RESPONSE"; })(exports.MessageType || (exports.MessageType = {})); exports.CorvinaPages = void 0; (function (CorvinaPages) { CorvinaPages["HOME"] = "home"; CorvinaPages["DASHBOARD"] = "dashboard"; CorvinaPages["DEVICE_ACTIVATE"] = "device-activate"; CorvinaPages["DEVICE_MANAGE"] = "device-manage"; CorvinaPages["DEVICE_VPN"] = "device-vpn"; CorvinaPages["DATA_CONFIGURE"] = "data-configure"; CorvinaPages["DATA_EXPLORE"] = "data-explore"; CorvinaPages["DATA_ALARMS"] = "data-alarms"; CorvinaPages["DATA_NOTIFICATIONS"] = "data-notifications"; CorvinaPages["IAM_ORGANIZATIONS"] = "iam-organizations"; CorvinaPages["IAM_USERS"] = "iam-users"; CorvinaPages["IAM_ROLES"] = "iam-roles"; CorvinaPages["DEALER"] = "dealer"; CorvinaPages["AUDIT"] = "audit"; CorvinaPages["LOG"] = "log"; })(exports.CorvinaPages || (exports.CorvinaPages = {})); const appHrefQueryString = 'appHref'; var TransactionsAuthorizationDialogResponseMessage; (function (TransactionsAuthorizationDialogResponseMessage) { TransactionsAuthorizationDialogResponseMessage["AUTHORIZED"] = "AUTHORIZED"; TransactionsAuthorizationDialogResponseMessage["USER_REJECTED"] = "USER_REJECTED"; TransactionsAuthorizationDialogResponseMessage["ERROR_NO_EMPTY_TRANSACTIONS"] = "ERROR_NO_EMPTY_TRANSACTIONS"; TransactionsAuthorizationDialogResponseMessage["ERROR_NO_IN_APP_PURCHASES"] = "ERROR_NO_IN_APP_PURCHASES"; })(TransactionsAuthorizationDialogResponseMessage || (TransactionsAuthorizationDialogResponseMessage = {})); class UrlWatcher { constructor(onUrlChange, currentWindow) { this._window = window; this._window = currentWindow || window; this._onUrlChange = onUrlChange; this._originalPushState = this._window.history.pushState; this._originalReplaceState = this._window.history.replaceState; this._window.history.pushState = (...args) => { this._originalPushState.apply(this._window.history, args); this._onUrlChange({ type: 'pushState' }); }; this._window.history.replaceState = (...args) => { this._originalReplaceState.apply(this._window.history, args); this._onUrlChange({ type: 'replaceState' }); }; this._window.addEventListener("popstate", this._onUrlChange); } dispose() { this._window.history.pushState = this._originalPushState; this._window.history.replaceState = this._originalReplaceState; this._window.removeEventListener("popstate", this._onUrlChange); } static extractAppHref() { try { const url = new URL(window.location.href); let appHref = url.searchParams.get(appHrefQueryString); if (!appHref) { appHref = (new URLSearchParams(url.hash.slice(url.hash.indexOf('?')))).get(appHrefQueryString); } if (appHref) { return decodeURIComponent(appHref); } } catch (error) { console.warn("CorvinaHost: Error extracting appHref from ", window.location.href); } return undefined; } setAppHref(appHref, type) { const applyPath = (path) => { if (type === 'replaceState') { this._originalReplaceState.call(this._window.history, null, "", path); } else { this._originalPushState.call(this._window.history, null, "", path); } }; if (this._window.location.hash) { let queryParamsPos = this._window.location.hash.indexOf("?"); if (queryParamsPos < 0) { applyPath(this._window.location.hash + "?" + appHrefQueryString + "=" + encodeURIComponent(appHref)); } else { const params = new URLSearchParams(this._window.location.hash.slice(queryParamsPos)); params.set(appHrefQueryString, appHref); const newHash = this._window.location.hash.slice(0, queryParamsPos + 1) + params; applyPath(newHash); } } else { const url = new URL(this._window.location.href); url.searchParams.set(appHrefQueryString, appHref); applyPath(url.toString()); } } } var __awaiter$1 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class CorvinaHost { constructor({ jwtApp, username, organizationId, organizationResourceId, corvinaHost, corvinaDomain, theme, defaultStandardTime, brandName, }) { this._jwtApp = jwtApp; this._username = username; this._organizationId = organizationId; this._organizationResourceId = organizationResourceId; this._corvinaHost = corvinaHost; this._corvinaDomain = corvinaDomain; this._theme = theme; this._defaultStandardTime = defaultStandardTime; this._onMessageRef = this.onMessage.bind(this); this._brandName = brandName; window.addEventListener("message", this._onMessageRef); } dispose() { var _a; window.removeEventListener("message", this._onMessageRef); (_a = this._urlWatcher) === null || _a === void 0 ? void 0 : _a.dispose(); this._urlWatcher = undefined; } onNavigate(callback) { this._onNavigateCallback = callback; } onPreauthorizedTransactionAuthorizationRequest(callback) { this._onPreauthorizedTransactionAuthorizationRequestCallback = callback; } setJwtApp(jwtApp) { const message = { type: exports.MessageType.JWT_CHANGED, payload: { jwt: jwtApp.jwt, }, }; this._jwtApp.set(jwtApp.iframeOrigin, jwtApp); this.sendMessageToFrame(message, jwtApp.iframeOrigin); } set username(username) { this._username = username; const message = { type: exports.MessageType.USER_CHANGED, payload: { username, }, }; this.sendMessageToAllFrames(message); } set organizationId(organizationId) { this._organizationId = organizationId; const message = { type: exports.MessageType.ORGANIZATION_ID_CHANGED, payload: { organizationId, }, }; this.sendMessageToAllFrames(message); } set organizationResourceId(organizationResourceId) { this._organizationResourceId = organizationResourceId; const message = { type: exports.MessageType.ORGANIZATION_RESOURCE_ID_CHANGED, payload: { organizationResourceId, }, }; this.sendMessageToAllFrames(message); } set theme(theme) { this._theme = theme; const message = { type: exports.MessageType.THEME_CHANGED, payload: { theme, }, }; this.sendMessageToAllFrames(message); } set brandName(brandName) { this._brandName = brandName; const message = { type: exports.MessageType.BRAND_NAME_CHANGED, payload: { brandName, }, }; this.sendMessageToAllFrames(message); } set defaultStandardTime(defaultStandardTime) { this._defaultStandardTime = defaultStandardTime; } get defaultStandardTime() { return this._defaultStandardTime; } get organizationId() { return this._organizationId; } get theme() { return this._theme; } get brandName() { return this._brandName; } sendMessageToAllFrames(message) { var _a; const iframes = document.getElementsByTagName("iframe"); for (const iframe of iframes) { if (iframe.id && iframe.id.startsWith("corvina-app-connect-")) { (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage(message, { targetOrigin: iframe.src, }); } } } sendMessageToFrame(message, iframeOrigin) { var _a; const iframes = document.querySelectorAll(`iframe[src^='${iframeOrigin}']`); for (const iframe of iframes) { (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage(message, { targetOrigin: iframe.src, }); } } onMessage(event) { var _a, _b; console.debug("CorvinaHost: onMessage", event.data); switch (event.data.type) { case exports.MessageType.CORVINA_CONNECT_INIT: this.onCorvinaConnectInit(event); break; case exports.MessageType.CORVINA_NAVIGATE: if (!this._onNavigateCallback) { console.warn("CorvinaHost: onNavigate callback is not defined"); break; } (_a = this._onNavigateCallback) === null || _a === void 0 ? void 0 : _a.call(this, event.data.payload); break; case exports.MessageType.IFRAME_HREF_CHANGED: if (event.data.payload.href && this._appHref !== event.data.payload.href) { this._appHref = event.data.payload.href; if (this._urlWatcher && this._appHref) { this._urlWatcher.setAppHref(this._appHref, event.data.payload.type); } } break; case exports.MessageType.TRANSACTIONS_AUTHORIZATION_REQUEST: if (!this._onPreauthorizedTransactionAuthorizationRequestCallback) { console.warn("CorvinaHost: onPaymentAuthorizationRequest callback is not defined"); break; } (_b = this._onPreauthorizedTransactionAuthorizationRequestCallback) === null || _b === void 0 ? void 0 : _b.call(this, event); break; } } onCorvinaConnectInit(event) { var _a; const response = { type: exports.MessageType.CORVINA_CONNECT_INIT_RESPONSE, payload: { jwt: (_a = this._jwtApp.get(event.origin)) === null || _a === void 0 ? void 0 : _a.jwt, username: this._username, organizationId: this._organizationId, organizationResourceId: this._organizationResourceId, corvinaHost: this._corvinaHost, corvinaDomain: this._corvinaDomain, theme: this._theme, defaultStandardTime: this._defaultStandardTime, brandName: this._brandName, }, }; if (event.source) { event.source.postMessage(response, { targetOrigin: event.origin }); } else { console.warn("CorvinaHost: Event source is not defined", event); } } static create(_a) { return __awaiter$1(this, arguments, void 0, function* ({ jwtApp, username, organizationId, organizationResourceId, corvinaHost, corvinaDomain, theme, defaultStandardTime, brandName, }) { return new CorvinaHost({ jwtApp, username, organizationId, organizationResourceId, corvinaHost, corvinaDomain, theme, defaultStandardTime, brandName }); }); } enableNavigationSync() { this._appHref = UrlWatcher.extractAppHref(); this._urlWatcher = new UrlWatcher(({ type }) => { const newAppHref = UrlWatcher.extractAppHref(); if (newAppHref !== this._appHref) { const message = { type: exports.MessageType.IFRAME_HREF_CHANGED, payload: { href: newAppHref, type }, }; this.sendMessageToAllFrames(message); this._appHref = newAppHref; } }); } disableNavigationSync() { var _a; (_a = this._urlWatcher) === null || _a === void 0 ? void 0 : _a.dispose(); this._urlWatcher = undefined; } } var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; exports.CorvinaConnectEventType = void 0; (function (CorvinaConnectEventType) { CorvinaConnectEventType["ORGANIZATION_ID_CHANGED"] = "ORGANIZATION_ID_CHANGED"; CorvinaConnectEventType["ORGANIZATION_RESOURCE_ID_CHANGED"] = "ORGANIZATION_RESOURCE_ID_CHANGED"; CorvinaConnectEventType["JWT_CHANGED"] = "JWT_CHANGED"; CorvinaConnectEventType["USER_CHANGED"] = "USER_CHANGED"; CorvinaConnectEventType["THEME_CHANGED"] = "THEME_CHANGED"; CorvinaConnectEventType["BRAND_NAME_CHANGED"] = "BRAND_NAME_CHANGED"; CorvinaConnectEventType["IFRAME_HREF_CHANGED"] = "IFRAME_HREF_CHANGED"; CorvinaConnectEventType["TRANSACTIONS_AUTHORIZATION_RESPONSE"] = "TRANSACTIONS_AUTHORIZATION_RESPONSE"; })(exports.CorvinaConnectEventType || (exports.CorvinaConnectEventType = {})); const initHandshake = ({ currentWindow, corvinaHostWindow, corvinaHost }) => { return new Promise((resolve, reject) => { try { corvinaHostWindow === null || corvinaHostWindow === void 0 ? void 0 : corvinaHostWindow.postMessage({ type: exports.MessageType.CORVINA_CONNECT_INIT }, corvinaHost); const handleInitResponse = (event) => { console.debug("CorvinaConnect: onMessage", event.data); let message = event.data; if (message.type === exports.MessageType.CORVINA_CONNECT_INIT_RESPONSE) { let { corvinaDomain, jwt, username, organizationId, organizationResourceId, defaultStandardTime, theme, brandName } = message.payload; currentWindow.removeEventListener("message", handleInitResponse, false); resolve(new CorvinaConnect({ jwt, username, organizationId, organizationResourceId, corvinaHost, corvinaDomain, theme, defaultStandardTime, currentWindow, corvinaHostWindow, brandName })); } }; currentWindow.addEventListener('message', handleInitResponse); } catch (error) { reject(error); } }); }; class CorvinaConnect { constructor({ jwt, username, organizationId, organizationResourceId, corvinaHost, corvinaDomain, theme, brandName, defaultStandardTime, currentWindow, corvinaHostWindow }) { this._eventCallback = {}; if (!jwt) { throw new Error('JWT is required'); } if (!username) { throw new Error('Username is required'); } if (!organizationId) { throw new Error('OrganizationId is required'); } if (!organizationResourceId) { throw new Error('OrganizationResourceId is required'); } if (!corvinaHost) { throw new Error('CorvinaHost is required'); } if (!corvinaDomain) { throw new Error('CorvinaDomain is required'); } if (!corvinaHostWindow) { throw new Error('CorvinaHostWindow is required'); } this._jwt = jwt; this._username = username; this._organizationId = organizationId; this._organizationResourceId = organizationResourceId; this._corvinaHost = corvinaHost; this._corvinaDomain = corvinaDomain; this._theme = theme; this._defaultStandardTime = defaultStandardTime; this._corvinaHostWindow = corvinaHostWindow; this._brandName = brandName; this._window = currentWindow || window; this._eventCallback = Object.keys(exports.CorvinaConnectEventType).reduce((acc, key) => { acc[key] = []; return acc; }, {}); this._onMessageRef = this.onMessage.bind(this); this._window.addEventListener("message", this._onMessageRef); } static dispose() { if (CorvinaConnect._instance) { CorvinaConnect._instance.dispose(); CorvinaConnect._instance = undefined; } } dispose() { var _a; this._window.removeEventListener("message", this._onMessageRef); (_a = this._urlWatcher) === null || _a === void 0 ? void 0 : _a.dispose(); this._urlWatcher = undefined; } get jwt() { return this._jwt; } get username() { return this._username; } get organizationId() { return this._organizationId; } get organizationResourceId() { return this._organizationResourceId; } get corvinaHost() { return this._corvinaHost; } get corvinaDomain() { return this._corvinaDomain; } get theme() { return this._theme; } get defaultStandardTime() { return this._defaultStandardTime; } get brandName() { return this._brandName; } onMessage(event) { console.debug("CorvinaConnect: onMessage", event.data); switch (event.data.type) { case exports.MessageType.USER_CHANGED: this.onUserChanged(event); break; case exports.MessageType.JWT_CHANGED: this.onJwtChanged(event); break; case exports.MessageType.ORGANIZATION_ID_CHANGED: this.onOrganizationIdChanged(event); break; case exports.MessageType.ORGANIZATION_RESOURCE_ID_CHANGED: this.onOrganizationResourceIdChanged(event); break; case exports.MessageType.THEME_CHANGED: this.onThemeChanged(event); break; case exports.MessageType.BRAND_NAME_CHANGED: this.onBrandNameChanged(event); break; case exports.MessageType.IFRAME_HREF_CHANGED: this.onIframeHrefChanged(event); break; case exports.MessageType.TRANSACTIONS_AUTHORIZATION_RESPONSE: this.onPreauthorizedTransactionResponse(event); break; } } onThemeChanged(event) { this._theme = event.data.payload.theme; for (const callback of this._eventCallback[exports.CorvinaConnectEventType.THEME_CHANGED]) { callback(this._theme); } } onBrandNameChanged(event) { this._brandName = event.data.payload.brandName; for (const callback of this._eventCallback[exports.CorvinaConnectEventType.BRAND_NAME_CHANGED]) { callback(this._brandName); } } onUserChanged(event) { this._username = event.data.payload.username; for (const callback of this._eventCallback[exports.CorvinaConnectEventType.USER_CHANGED]) { callback(this._username); } } onJwtChanged(event) { this._jwt = event.data.payload.jwt; for (const callback of this._eventCallback[exports.CorvinaConnectEventType.JWT_CHANGED]) { callback(this._jwt); } } onOrganizationIdChanged(event) { this._organizationId = event.data.payload.organizationId; for (const callback of this._eventCallback[exports.CorvinaConnectEventType.ORGANIZATION_ID_CHANGED]) { callback(this._organizationId); } } onOrganizationResourceIdChanged(event) { this._organizationResourceId = event.data.payload.organizationResourceId; for (const callback of this._eventCallback[exports.CorvinaConnectEventType.ORGANIZATION_RESOURCE_ID_CHANGED]) { callback(this._organizationResourceId); } } onIframeHrefChanged(event) { for (const callback of this._eventCallback[exports.CorvinaConnectEventType.IFRAME_HREF_CHANGED]) { callback(event.data.payload); } } onPreauthorizedTransactionResponse(event) { for (const callback of this._eventCallback[exports.CorvinaConnectEventType.TRANSACTIONS_AUTHORIZATION_RESPONSE]) { callback(event.data.payload); } } off(event) { if (!event) { throw new Error("Event name is required"); } this._eventCallback[event] = []; } on(event, callback) { if (!event) { throw new Error("Event name is required"); } if (!Object.values(exports.CorvinaConnectEventType).includes(event)) { throw new Error("Event name is not valid"); } if (!callback) { throw new Error("Callback is required"); } this._eventCallback[event].push(callback); } navigateTo(page) { if (!page) { throw new Error("Path is required"); } const message = { type: exports.MessageType.CORVINA_NAVIGATE, payload: { page } }; this._corvinaHostWindow.postMessage(message, this._corvinaHost); } static create(_a) { return __awaiter(this, arguments, void 0, function* ({ corvinaHost, currentWindow, corvinaHostWindow, timeoutMs }) { currentWindow = currentWindow || window; if (!this._instance) { corvinaHostWindow = corvinaHostWindow || currentWindow.parent.window; const initHandshakePromise = initHandshake({ currentWindow, corvinaHostWindow, corvinaHost }); const timeoutPromise = new Promise((resolve, reject) => { setTimeout(reject, timeoutMs !== null && timeoutMs !== void 0 ? timeoutMs : 5000, 'Create timeout reached'); }); this._instance = (yield Promise.race([initHandshakePromise, timeoutPromise])); } return this._instance; }); } enableNavigationSync(filterNewHref = (newHref) => newHref) { this._href = this._window.location.href; this._urlWatcher = new UrlWatcher(({ type }) => { const newHref = filterNewHref(this._window.location.href); if (newHref !== this._href) { const message = { type: exports.MessageType.IFRAME_HREF_CHANGED, payload: { href: newHref, type }, }; this._corvinaHostWindow.postMessage(message, this._corvinaHost); } }, this._window); } disableNavigationSync() { var _a; (_a = this._urlWatcher) === null || _a === void 0 ? void 0 : _a.dispose(); this._urlWatcher = undefined; } promptPreauthorizedTransactionAuthorization(dto) { const message = { type: exports.MessageType.TRANSACTIONS_AUTHORIZATION_REQUEST, payload: dto }; this._corvinaHostWindow.postMessage(message, this._corvinaHost); } } exports.CorvinaConnect = CorvinaConnect; exports.CorvinaHost = CorvinaHost; }));