Skip to content

Commit

Permalink
Merge pull request #5154 from storybooks/ts-migration/channel-postmes…
Browse files Browse the repository at this point in the history
…sage

Migrate @storybook/channel-postmessage to TypeScript
  • Loading branch information
ndelangen committed Jan 7, 2019
2 parents 0d89220 + f144a3c commit dece5f0
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 21 deletions.
5 changes: 4 additions & 1 deletion lib/channel-postmessage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"license": "MIT",
"main": "dist/index.js",
"jsnext:main": "src/index.js",
"types": "dist/index.d.ts",
"scripts": {
"prepare": "node ../../scripts/prepare.js"
},
Expand All @@ -24,6 +24,9 @@
"global": "^4.3.2",
"json-stringify-safe": "^5.0.1"
},
"devDependencies": {
"@types/json-stringify-safe": "^5.0.0"
},
"publishConfig": {
"access": "public"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,73 @@
/* eslint-disable no-underscore-dangle */

import { window, document } from 'global';
import Channel from '@storybook/channels';
import Channel, { ChannelEvent, ChannelHandler } from '@storybook/channels';
import stringify from 'json-stringify-safe';

interface RawEvent {
data: string;
}

interface Config {
page: 'manager' | 'preview';
}

interface BufferedEvent {
event: ChannelEvent;
resolve: (value?: any) => void;
reject: (reason?: any) => void;
}

export const KEY = 'storybook-channel';

export class PostmsgTransport {
constructor(config) {
this._config = config;
this._buffer = [];
this._handler = null;
window.addEventListener('message', this._handleEvent.bind(this), false);
document.addEventListener('DOMContentLoaded', () => this._flush());
private buffer: BufferedEvent[];
private handler: ChannelHandler;

constructor(private readonly config: Config) {
this.buffer = [];
this.handler = null;
window.addEventListener('message', this.handleEvent.bind(this), false);
document.addEventListener('DOMContentLoaded', () => this.flush());
// Check whether the config.page parameter has a valid value
if (config.page !== 'manager' && config.page !== 'preview') {
throw new Error(`postmsg-channel: "config.page" cannot be "${config.page}"`);
}
}

setHandler(handler) {
this._handler = handler;
setHandler(handler: ChannelHandler): void {
this.handler = handler;
}

send(event) {
const iframeWindow = this._getWindow();
/**
* Sends `event` to the associated window. If the window does not yet exist
* the event will be stored in a buffer and sent when the window exists.
* @param event
*/
send(event: ChannelEvent): Promise<any> {
const iframeWindow = this.getWindow();
if (!iframeWindow) {
return new Promise((resolve, reject) => {
this._buffer.push({ event, resolve, reject });
this.buffer.push({ event, resolve, reject });
});
}
const data = stringify({ key: KEY, event });
iframeWindow.postMessage(data, '*');
return Promise.resolve(null);
}

_flush() {
const buffer = this._buffer;
this._buffer = [];
private flush(): void {
const buffer = this.buffer;
this.buffer = [];
buffer.forEach(item => {
this.send(item.event)
.then(item.resolve)
.catch(item.reject);
});
}

_getWindow() {
if (this._config.page === 'manager') {
private getWindow(): Window {
if (this.config.page === 'manager') {
// FIXME this is a really bad idea! use a better way to do this.
// This finds the storybook preview iframe to send messages to.
const iframe = document.getElementById('storybook-preview-iframe');
Expand All @@ -58,18 +79,21 @@ export class PostmsgTransport {
return window.parent;
}

_handleEvent(rawEvent) {
private handleEvent(rawEvent: RawEvent): void {
try {
const { data } = rawEvent;
const { key, event } = JSON.parse(data);
if (key === KEY) {
this._handler(event);
this.handler(event);
}
} catch (error) {} // eslint-disable-line
}
}

export default function createChannel({ page }) {
/**
* Creates a channel which communicates with an iframe or child window.
*/
export default function createChannel({ page }: Config): Channel {
const transport = new PostmsgTransport({ page });
return new Channel({ transport });
}
1 change: 1 addition & 0 deletions lib/channel-postmessage/src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module 'global';
8 changes: 8 additions & 0 deletions lib/channel-postmessage/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["src/**.test.ts"]
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,11 @@
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.12.tgz#7e0ced251fa94c3bc2d1023d4b84b2992fa06376"
integrity sha512-/kQvbVzdEpOq4tEWT79yAHSM4nH4xMlhJv2GrLVQt4Qmo8yYsPdioBM1QpN/2GX1wkfMnyXvdoftvLUr0LBj7Q==

"@types/json-stringify-safe@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz#df34d054419d39323a3730966bacba02ac5e474e"
integrity sha512-UUA1sH0RSRROdInuDOA1yoRzbi5xVFD1RHCoOvNRPTNwR8zBkJ/84PZ6NhKVDtKp0FTeIccJCdQz1X2aJPr4uw==

"@types/json5@^0.0.29":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
Expand Down

0 comments on commit dece5f0

Please sign in to comment.