@mastercard/connect-components-web-sdk
Version:
The web SDK for the Connect Components project
132 lines (124 loc) • 3.98 kB
JavaScript
/**
* @param {import('./types').ElementImports} $inject
*/
function eventStream_injector($inject) {
const { appConfig, HTMLElement, logger, document, window } = $inject;
return class MastercardEventStream extends HTMLElement {
/**
* @constructor
* @type {import('./types').ElementExports['constructor']}
*/
constructor() {
super();
this.eventStreamId = null;
this.formId = null;
this.events = new EventTarget();
}
// - Static methods
/**
* @static
* @type {import('./types').ElementExports['observedAttributes']}
*/
static get observedAttributes() {
// @ts-ignore
return ['event-stream-id', 'form-id'];
}
// - Lifecycle Events
/**
* @type {import('./types').ElementExports['connectedCallback']}
*/
connectedCallback() {
const $elem = this;
if (!this.eventStreamId) {
this.eventStreamId = $elem.getAttribute('event-stream-id');
}
if (!this.formId && $elem.getAttribute('form-id')) {
this.formId = $elem.getAttribute('form-id');
} else if (!this.formId) {
try {
// This doesn't exist in the oauth rediretion flow
this.formId = $elem.closest('mastercard-form').getAttribute('id');
} catch (err) {
this.formId = 'default';
}
}
this.iframe = document.createElement('iframe');
$elem.append(this.iframe);
$elem.style.display = 'none';
if (this.eventStreamId) {
this._bindFrameSource();
this._registerEventListener();
}
}
/**
* @type {import('./types').ElementExports['attributeChangedCallback']}
*/
attributeChangedCallback(name, _oldValue, newValue) {
if (!this.isConnected) {
return;
}
if (name === 'event-stream-id') {
this.eventStreamId = newValue;
this._bindFrameSource();
this._registerEventListener();
}
}
// - Custom Methods
/**
* @access private
* @type {import('./types').ElementExports['_bindFrameSource']}
*/
_bindFrameSource() {
const frameSource = `${appConfig.getSDKBase()}/frames/parent/forms/event-stream.html?event-stream-id=${
this.eventStreamId
}&form-id=${this.formId}`;
// @ts-ignore
this.iframe.setAttribute('src', frameSource);
}
/**
* @access private
* @type {import('./types').ElementExports['_registerEventListener']}
*/
_registerEventListener() {
// @ts-ignore
window.addEventListener('message', (event) => {
if (event.origin !== appConfig.getFrameOrigin()) {
logger.warn(`Skipping message from ${event.origin}`);
return;
}
/*
There is some conversion that needs to happen here to make this event not look really messy.
First, we create a local event (instead of an SSE event), then we use the eventType from the
payload to determine the kind of event to send. Then we add the id of the event. Then we clear
out the payload of those values so we don't have duplicates
*/
const newEvent = new Event(event.data.eventType);
// @ts-ignore
newEvent.data = (event.data || {}).data;
// @ts-ignore
newEvent.id = (event.data || {}).id;
try {
// @ts-ignore
delete newEvent.data.isPublic;
// @ts-ignore
delete newEvent.data.eventType;
// @ts-ignore
delete newEvent.data.id;
} catch (err) {
logger.warn(err);
}
this.events.dispatchEvent(newEvent);
});
}
/**
* @method
* @type {import('./types').ElementExports['_isValidEventStreamId']}
*/
_isValidEventStreamId(id) {
const isValid =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return isValid.test(id);
}
};
}
export { eventStream_injector };