@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
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.$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;
}));