@2k/post-message
TypeScript icon, indicating that this package has built-in type declarations

0.0.11 • Public • Published

@2k/post-message

Simple promise based post message / listener.

Usage

(1) onMessage

import { onMessage } from '@2k/post-message';

const cb = async (msg) => {
    console.log(msg.oid, msg.origin, msg.data)
    // wait some async operation
    const resp = await foo(msg.data);
    return resp;
}

// source: all
const unSub_all = onMessage(cb);
const unSub_star = onMessage('*', cb);

// source: window
const unSub_1 = onMessage(
    window.parent,
    cb
);

// source: iframe
const unSub_2 = onMessage(
    document.getElementById('iframe'),
    cb // callback
);

// source: iframe.contentWindow
const unSub_3 = onMessage(
    document.getElementById('iframe').contentWindow,
    cb
);

(2) sendMessage

import { sendMessage } from '@2k/post-message';

// target: window
const resp_1 = await sendMessage(
    window.parent,
    { name: 'foo' },
    {
        needResponse: true,
        timeout: 10000 // response timeout
    }
);
console.log(resp_1.result)

// target: iframe
const resp_2 = await sendMessage(
    document.getElementById('iframe')
    { name: 'bar' },
);
console.log(resp_2.result)

// target: iframe.contentWindow
const resp_3 = await sendMessage(
    document.getElementById('iframe').contentWindow
    { name: 'baz' },
);
console.log(resp_3.result)

(3) Create a simple forwarding bridge

<!-- bridge.html--->
<script src="https://unpkg.com/@2k/post-message"></script>
<iframe id="iframeA" src="https://a.com/a.tml"></iframe>
<iframe id="iframeB" src="https://b.com/b.html"></iframe>
<script>
const {onMessage, sendMessage} = twoK
const iframeA = document.getElementById("iframeA");
const iframeB = document.getElementById("iframeB");
onMessage(iframeA, (msg) => sendMessage(iframeB, msg.data));
onMessage(iframeB, (msg) => sendMessage(iframeA, msg.data));
</script>

<!-- https://a.com/a.tml--->
<input id="input" type="text" value="a" onkeyup="send()">
<script>
const {onMessage, sendMessage} = twoK
onMessage(parent, async (msg) => {
    document.getElementById('input').value = msg.data
    return `A received : ${msg.data}`
})
async function send() {
    const value = document.getElementById('input').value
    const [err, res] = await sendMessage(parent, value, {
        needResponse: true,
        timeout: 1000
    }).then(res => [null, res], (err) => [err])
    console.log(['A send done', err, res?.result])
}
</script>

<!-- https://b.com/b.html--->
<input id="input" type="text" value="b" onkeyup="send()">
<script>
const {onMessage, sendMessage} = twoK
onMessage(parent, async (msg) => {
    document.getElementById('input').value = msg.data
    return `B received : ${msg.data}`
})
async function send() {
    const value = document.getElementById('input').value
    const [err, res] = await sendMessage(parent, value, {
        needResponse: true,
        timeout: 1000
    }).then(res => [null, res], (err) => [err])
    console.log(['B send done', err, res?.result])
}
</script>

Types

type Endpoint = 'parent' | 'child';
type SendOptions = {
    origin?: string;
    endpoint?: Endpoint;
    needsResponse?: boolean;
    timeout?: number;
};
type MsgBody<T> = {
    oid: number;
    data: T;
    ctime: number;
    origin?: string;
};
type MsgResp<T> = {
    oid: number;
    result: T;
    ctime: number;
};
type MsgCb<T, R> = (msg: MsgBody<T>) => Promise<R> | R;

/**
 * Listen to messages from a source frame.
 *
 * @param { function } cb - optional source frame, listens to all messages if not provided.
 * @returns { function } - unsubscribe function
 */
declare function onMessage<T, R>(cb: MsgCb<T, R>): () => boolean;

/**
 * Listen to messages from a source frame.
 *
 * @param { HTMLIFrameElement | Window | '*' | function } source - optional source frame, listens to all messages if not provided.
 * @param { function } cb - callback function
 * @returns { function } - unsubscribe function
 */
declare function onMessage<T, R>(
    source: HTMLIFrameElement | Window | '*',
    cb: MsgCb<T, R>): () => boolean;

/**
 * Listen to messages from a source DOM Node.
 *
 * @param { HTMLElement } source - optional source frame, listens to all messages if not provided.
 * @param { function } cb
 * @param { "parent" | "child" } endpoint
 * @returns { function } - unsubscribe function
 */
declare function onMessage<T, R>(
    source: HTMLElement,
    cb: MsgCb<T, R>,
    endpoint: Endpoint): () => boolean;

/**
 * Send messages to a target frame or DOM node.
 *
 * @param { HTMLIFrameElement | HTMLElement | Window } target - The target window | iframe | DOM node
 * @param { * } data - The message payload
 * @param { SendOptions } options - The options
 * @returns { Promise<Response> } - Response
 */
declare function sendMessage<T, R>(
    target: HTMLIFrameElement | HTMLElement | Window,
    data: T,
    options?: SendOptions): Promise<MsgResp<Awaited<R>>>;

Package Sidebar

Install

npm i @2k/post-message

Weekly Downloads

541

Version

0.0.11

License

MIT

Unpacked Size

13.3 kB

Total Files

6

Last publish

Collaborators

  • scriptpower