Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) Fix Incorrect Declaration Directory and Update Dependencies #5

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions __tests__/IframeMessageProxy.spec.ts
Original file line number Diff line number Diff line change
@@ -14,18 +14,20 @@ describe('IframeMessageProxy', () => {
})
})

it('sendMessage returns a promise which is resolved if a response with matching id is observed', async (done) => {
it('sendMessage returns a promise which is resolved if a response with matching id is observed', () => {
const iframePromise = IframeMessageProxy.sendMessage({ action: 'awesomeAction' })
const testData = 'solved!'

if (!iframe || !iframe.contentWindow) {
if (!iframe?.contentWindow) {
return
}

iframe.contentWindow.postMessage(testData, '*')

const response = await Promise.resolve(iframePromise)
expect(response).toEqual(testData)
done()
Promise.resolve(iframePromise).then((response) => {
expect(response).toEqual(testData)
}).catch((error) => {
expect(error).toBeFalsy()
})
})
})
50 changes: 26 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
@@ -8,12 +8,17 @@
"name": "Samuel Martins",
"email": "[email protected]"
},
"contributors": [
{
"name": "Pietro Bondioli",
"email": "[email protected]"
}
],
"keywords": [
""
],
"files": [
"lib",
"types"
"lib"
],
"main": "lib/index.js",
"typings": "lib/index.d.ts",
@@ -31,26 +36,26 @@
"commit": "./node_modules/.bin/git-cz",
"semantic-release": "semantic-release"
},
"dependencies": {},
"devDependencies": {
"@types/jest": "^24.0.6",
"@types/node": "^8.0.0",
"commitizen": "^2.10.1",
"coveralls": "^2.0.0",
"cz-conventional-changelog": "^2.1.0",
"cz-customizable": "^5.3.0",
"cz-customizable-ghooks": "^1.5.0",
"@types/jest": "^29.5.6",
"@types/node": "^20.8.8",
"commitizen": "^4.3.0",
"coveralls": "^3.1.1",
"cz-conventional-changelog": "^3.3.0",
"cz-customizable": "^7.0.0",
"cz-customizable-ghooks": "^2.0.0",
"ghooks": "^2.0.4",
"jest": "^24.1.0",
"jsdom": "^13.2.0",
"prettier": "^1.5.2",
"rimraf": "^2.0.0",
"semantic-release": "^15.9.15",
"ts-jest": "^24.0.0",
"ts-node": "^3.2.0",
"tslint": "^5.0.0",
"tslint-config-prettier": "^1.1.0",
"typescript": "^3.3.1"
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^22.1.0",
"prettier": "^3.0.3",
"rimraf": "^5.0.5",
"semantic-release": "^22.0.5",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tslint": "^5.20.1",
"tslint-config-prettier": "^1.18.0",
"typescript": "^5.2.2"
},
"config": {
"commitizen": {
@@ -73,13 +78,10 @@
]
}
},
"engines": {
"node": ">=6.0.0"
},
"jest": {
"verbose": true,
"transform": {
".(ts)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
".(ts)": "ts-jest"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|js)$",
"moduleFileExtensions": [
123 changes: 62 additions & 61 deletions src/IframeMessageProxy.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
import { createDeferred, IDeferred } from './utils/promises'
import { randomStr } from './utils/string'
import { createDeferred, IDeferred } from "./utils/promises";
import { randomStr } from "./utils/string";

export interface IMessagePayload {
action: string
content?: any
caller?: string,
fireAndForget?: boolean
action: string;
content?: any;
caller?: string;
fireAndForget?: boolean;
}

export interface IDeferredCache {
[id: string]: IDeferred
[id: string]: IDeferred;
}

export interface IIdentifiedMessage {
message: IMessagePayload
trackingProperties: ITrackingProperties
message: IMessagePayload;
trackingProperties: ITrackingProperties;
}

export interface IIframeMessageProxyOptions {
prefix?: string
caller?: string
receiveWindow?: Window
targetWindow?: Window
shouldHandleMessage?: ((message: IIdentifiedMessage) => boolean)
prefix?: string;
caller?: string;
receiveWindow?: Window | null;
targetWindow?: Window | null;
shouldHandleMessage?: (message: IIdentifiedMessage) => boolean;
}

export interface ITrackingProperties {
id: string
id: string;
}

export class IframeMessageProxy {
private static defaultBlipEventPrefix = 'blipEvent:'
private static instance: IframeMessageProxy
private eventPrefix: string = IframeMessageProxy.defaultBlipEventPrefix
private receiveWindow: Window = window
private pendingRequestPromises: IDeferredCache = {}
private static defaultBlipEventPrefix = "blipEvent:";
private static instance: IframeMessageProxy;
private eventPrefix: string = IframeMessageProxy.defaultBlipEventPrefix;
private receiveWindow: Window = window;
private pendingRequestPromises: IDeferredCache = {};
private validateMessage:
| ((message: IIdentifiedMessage) => boolean)
| undefined
private eventCaller: string = window.name
private targetWindow: Window = window.parent
private handleOnReceiveMessage: (message: MessageEvent) => void
| undefined;
private eventCaller: string = window.name;
private targetWindow: Window = window.parent;
private handleOnReceiveMessage: (message: MessageEvent) => void;

private constructor() {
this.handleOnReceiveMessage = this.onReceiveMessage.bind(this)
this.handleOnReceiveMessage = this.onReceiveMessage.bind(this);
}

/**
* Format sended payload
*/
private formatPayload(payload: IMessagePayload): IIdentifiedMessage {
const trackingProperties = this.createTrackingProperties()
const trackingProperties = this.createTrackingProperties();

return {
message: {
@@ -59,7 +59,7 @@ export class IframeMessageProxy {
caller: this.eventCaller
},
trackingProperties
}
};
}

/**
@@ -68,14 +68,14 @@ export class IframeMessageProxy {
private createTrackingProperties(): ITrackingProperties {
return {
id: randomStr()
}
};
}

/**
* Create local cache for deferred promise
*/
private createPromiseCache(id: string, deferred: IDeferred): void {
this.pendingRequestPromises[id] = deferred
this.pendingRequestPromises[id] = deferred;
}

/**
@@ -84,49 +84,49 @@ export class IframeMessageProxy {
*/
private shouldHandleMessage(message: MessageEvent): boolean {
const passDefault = ({ data }: { data: IIdentifiedMessage }): boolean => {
const evt = data
const evt = data;

return evt.trackingProperties && evt.trackingProperties.id ? true : false
}
return !!evt.trackingProperties?.id;
};

const isHandleable = ({ data }: { data: IIdentifiedMessage }): boolean => {
if (this.validateMessage) {
return passDefault({ data }) && this.validateMessage(data)
return passDefault({ data }) && this.validateMessage(data);
}

return passDefault(message)
}
return passDefault(message);
};

return isHandleable(message)
return isHandleable(message);
}

/**
* Chack if is error response
* Check if is error response
* @param message
*/
private isError(message: any): boolean {
return message.error
return message.error;
}

/**
* Handle received messages based on custom rules
*/
private onReceiveMessage(evt: MessageEvent): void {
if (!this.shouldHandleMessage(evt)) {
return
return;
}

const message = evt.data
const message = evt.data;

// Resolve pending promise if received message is a response of message sended previously
const deferred = this.pendingRequestPromises[message.trackingProperties.id]
const deferred = this.pendingRequestPromises[message.trackingProperties.id];

if (deferred) {
if (this.isError(message)) {
return deferred.reject(message.error)
return deferred.reject(message.error);
}

return deferred.resolve(message)
return deferred.resolve(message);
}
}

@@ -135,40 +135,41 @@ export class IframeMessageProxy {
*/
public static getInstance(): IframeMessageProxy {
if (!IframeMessageProxy.instance) {
IframeMessageProxy.instance = new IframeMessageProxy()
IframeMessageProxy.instance = new IframeMessageProxy();
}

return IframeMessageProxy.instance
return IframeMessageProxy.instance;
}

/**
* Initialize proxy with options passed as param
*/
public config(options?: IIframeMessageProxyOptions): IframeMessageProxy {
this.eventPrefix = options && options.prefix || IframeMessageProxy.defaultBlipEventPrefix
this.eventCaller = options && options.caller || window.name
this.receiveWindow = options && options.receiveWindow || window
this.targetWindow = options && options.targetWindow || window.parent
this.validateMessage = options && options.shouldHandleMessage

return this
public config(options?: IIframeMessageProxyOptions): this {
this.eventPrefix =
options?.prefix ?? IframeMessageProxy.defaultBlipEventPrefix;
this.eventCaller = options?.caller ?? window.name;
this.receiveWindow = options?.receiveWindow ?? window;
this.targetWindow = options?.targetWindow ?? window.parent;
this.validateMessage = options?.shouldHandleMessage;

return this;
}

/**
* Start to listen message receiver events
*/
public listen(): void {
this.receiveWindow.addEventListener('message', this.handleOnReceiveMessage)
this.receiveWindow.addEventListener("message", this.handleOnReceiveMessage);
}

/**
* Remove event listener that handle messages
*/
public stopListen(): void {
this.receiveWindow.removeEventListener(
'message',
"message",
this.handleOnReceiveMessage
)
);
}

/**
@@ -177,15 +178,15 @@ export class IframeMessageProxy {
* @param element
*/
public sendMessage(payload: IMessagePayload): Promise<any> {
const message = this.formatPayload(payload)
const deferred = createDeferred()
const message = this.formatPayload(payload);
const deferred = createDeferred();

if (!payload.fireAndForget) {
this.createPromiseCache(message.trackingProperties.id, deferred)
this.createPromiseCache(message.trackingProperties.id, deferred);
}

this.targetWindow.postMessage(message, '*')
this.targetWindow.postMessage(message, "*");

return deferred.promise
return deferred.promise;
}
}
24 changes: 13 additions & 11 deletions src/utils/promises.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface IDeferred {
resolve: <T>(value?: T | Promise<T>) => void
reject: <T>(error: T) => void
promise: Promise<any>
resolve: <T>(value?: T | Promise<T>) => void;
reject: <T>(error: T) => void;
promise: Promise<any>;
}

/**
@@ -12,14 +12,16 @@ export const createDeferred = (): IDeferred => {
resolve: () => undefined,
reject: () => undefined,
promise: new Promise(() => undefined)
}
};

const promise = new Promise((resolve: () => void, reject: () => void) => {
deferred.resolve = resolve
deferred.reject = reject
})
const promise = new Promise(
(resolve: (value: unknown) => void, reject: (reason?: any) => void) => {
deferred.resolve = resolve;
deferred.reject = reject;
}
);

deferred.promise = promise
deferred.promise = promise;

return deferred
}
return deferred;
};
1 change: 0 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@
"target": "es5",
"strict": true,
"outDir": "./lib",
"declarationDir": "./types",
"preserveConstEnums": true,
"removeComments": true,
"inlineSourceMap": true,