Skip to content

Commit

Permalink
Add custom tags and handlers support
Browse files Browse the repository at this point in the history
  • Loading branch information
andregoncalvesdev committed Jan 22, 2024
1 parent e15b5f1 commit 1c8469d
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/enums/events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export enum Events {
ALL = '*',
// Topper
ORDER_PLACED = 'orderPlaced',
WIDGET_CONTINUE_BUTTON_CLICKED = 'widgetContinueButtonClicked'
WIDGET_CONTINUE_BUTTON_CLICKED = 'widgetContinueButtonClicked',
// Internal
RESOLVE_HANDLER = 'resolveHandler'
}
3 changes: 3 additions & 0 deletions src/enums/handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum Handlers {
ASSETS = 'assets'
}
2 changes: 2 additions & 0 deletions src/enums/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './environments';
export * from './events';
export * from './handlers';
export * from './sources';
export * from './urls';
export * from './variants';
4 changes: 4 additions & 0 deletions src/enums/sources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Sources {
EVENT = '@topper-web-sdk-event',
HANDLER = '@topper-web-sdk-handler'
}
3 changes: 2 additions & 1 deletion src/interfaces/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface Config {
environment?: Environments;
is_android_app?: boolean;
is_ios_app?: boolean;
variant?: Variants;
theme?: string;
use_assets?: boolean;
variant?: Variants;
}
70 changes: 62 additions & 8 deletions src/topper-web-sdk.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Config } from './interfaces';
import { Environments, Events, Urls, Variants } from './enums';
import { EventHandler } from 'types';
import { Environments, Events, Handlers, Sources, Urls, Variants } from './enums';
import { EventHandler, Handler } from 'types';
import isPromise from 'utils/isPromise';
import queryString from 'query-string';

const TOPPER_WEB_SDK_EVENT_SOURCE = '@topper-web-sdk';

class TopperWebSdk {
private eventHandlers: { [key in Events]?: EventHandler[] } = {};
private handlers: { [key in Handlers]?: Handler } = {};
private handleMessage: ((event: MessageEvent) => void) | null = null;
private isInitialized: boolean = false;
private targetWindow: Window | null = null;
Expand All @@ -18,13 +18,39 @@ class TopperWebSdk {
environment: Environments.PRODUCTION,
is_android_app: false,
is_ios_app: false,
use_assets: false,
variant: Variants.NEW_TAB,
...config
};
}

static getMainWindow() {
return window.self !== window.top ? window.parent : window.opener;
}

static resolveHandler(handlerName: Handlers): Promise<void> {
const mainWindow = this.getMainWindow();

mainWindow.postMessage(
{
name: Events.RESOLVE_HANDLER,
payload: handlerName,
source: Sources.HANDLER
},
'*'
);

return new Promise(resolve => {
window.addEventListener('message', event => {
if (event.data.name === Events.RESOLVE_HANDLER && event.data.payload && event.data.source === Sources.HANDLER) {
resolve(event.data.payload);
}
});
});
}

static triggerEvent(eventName: Events, data?: any): void {
const mainWindow = window.self !== window.top ? window.parent : window.opener;
const mainWindow = this.getMainWindow();

if (!mainWindow) {
return;
Expand All @@ -34,7 +60,7 @@ class TopperWebSdk {
{
name: eventName,
payload: data,
source: TOPPER_WEB_SDK_EVENT_SOURCE
source: Sources.EVENT
},
'*'
);
Expand All @@ -54,9 +80,13 @@ class TopperWebSdk {
return;
}

if (event.data && event.data.name && event.data.source === TOPPER_WEB_SDK_EVENT_SOURCE) {
if (event.data.name && event.data.source === Sources.EVENT) {
this.triggerEvent(event.data.name as Events, event.data.payload);
}

if (event.data.name === Events.RESOLVE_HANDLER && event.data.payload && event.data.source === Sources.HANDLER) {
this.resolveHandler(event.data.payload as Handlers);
}
};

window.addEventListener('message', this.handleMessage);
Expand All @@ -82,7 +112,8 @@ class TopperWebSdk {
...(isTopperSelfEmbed && { embed: 1 }),
...(this.config.theme && { theme: this.config.theme }),
...(this.config.is_android_app && { is_android_app: 1 }),
...(this.config.is_ios_app && { is_ios_app: 1 })
...(this.config.is_ios_app && { is_ios_app: 1 }),
...(this.config.use_assets && { use_assets: 1 })
};

const url = queryString.stringifyUrl({ query: queryParams, url: `${baseUrl}/` });
Expand Down Expand Up @@ -112,6 +143,29 @@ class TopperWebSdk {

this.eventHandlers[eventName]?.push(handler);
}

registerHandler(handlerName: Handlers, handler: Handler): void {
if (!(typeof handler === 'function' || isPromise(handler))) {
throw new Error('Handler must be a Promise or an async function.');
}

this.handlers[handlerName] = handler;
}

async resolveHandler(handlerName: Handlers) {
const handler = this.handlers[handlerName];

const handlerResult = isPromise(handler) ? await handler : await handler?.();

this.targetWindow?.postMessage(
{
name: Events.RESOLVE_HANDLER,
payload: handlerResult,
source: Sources.HANDLER
},
'*'
);
}
}

export { TopperWebSdk };
1 change: 1 addition & 0 deletions src/types/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Handler = () => Promise<void>;
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './event-handler';
export * from './handler';
7 changes: 7 additions & 0 deletions src/utils/isPromise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const isObject = (value: any) => value !== null && (typeof value === 'object' || typeof value === 'function');

const isPromise = (value: any) =>
value instanceof Promise ||
(isObject(value) && typeof value.then === 'function' && typeof value.catch === 'function');

export default isPromise;

0 comments on commit 1c8469d

Please sign in to comment.