0.0.11 • Published 10 months ago

@2k/post-message v0.0.11

Weekly downloads
-
License
MIT
Repository
-
Last release
10 months ago

@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>>>;
0.0.11

10 months ago

0.0.10

10 months ago

0.0.9

10 months ago

0.0.8

10 months ago

0.0.7

10 months ago

0.0.6

10 months ago

0.0.5

10 months ago

0.0.4

10 months ago

0.0.3

10 months ago

0.0.2

10 months ago