Skip to content

Commit

Permalink
docs: recommend polyfill
Browse files Browse the repository at this point in the history
  • Loading branch information
hugojosefson committed Jul 13, 2023
1 parent 69696a9 commit 69394b8
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 79 deletions.
69 changes: 41 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

An implementation of
[BroadcastChannel](https://developer.mozilla.org/docs/Web/API/BroadcastChannel)
for Deno, that uses
for Deno CLI, that uses
[WebSocket](https://developer.mozilla.org/docs/Web/API/WebSocket)s to
communicate between processes on the same host.

Expand All @@ -17,7 +17,8 @@ BroadcastChannel, will let you do so.

(At least until Deno will
[Support cross process BroadcastChannel #10750](https://github.com/denoland/deno/issues/10750)
in the `deno` CLI itself.)
in the `deno` CLI itself, which is planned, but blocked on
[an upstream issue](https://github.com/tokio-rs/mio/pull/1667).)

## Requirements

Expand All @@ -37,10 +38,30 @@ For specifics on what this module `export`s, see the auto-generated API docs at

## Example usage

Instead of using the built-in `BroadcastChannel` constructor, use this module's
`createBroadcastChannel(name)` function.
### With BroadcastChannel polyfill

It will either:
The easiest way to use this module, is to use the included polyfill.

Import it as early as possible in your code, before any other imports that may
use `BroadcastChannel`.

```typescript
import "https://deno.land/x/websocket_broadcastchannel/polyfill.ts";

const channel = new BroadcastChannel("my-channel");
// Now use the channel as usual.
```

The polyfill does nothing if `BroadcastChannel` is already defined (on Deno
Deploy), and otherwise defines a global `BroadcastChannel` to use this module's
implementation.

### Without polyfill

For finer control, you may use the `createBroadcastChannel(name)` function,
instead of `new BroadcastChannel(name)` via the polyfill.

Calling the `createBroadcastChannel(name)` function will either:

- return a `BroadcastChannel` object if available (when running in Deno Deploy),
or
Expand All @@ -58,13 +79,10 @@ const channel = createBroadcastChannel("my-channel");
A small example, that you can run in several terminals on the same host, and see
messages broadcast between them.

This uses this module's
[createBroadcastChannel(name)](https://deno.land/x/websocket_broadcastchannel/mod.ts?s=createBroadcastChannel)
function to create the relevant `BroadcastChannel` object, and then uses the
`BroadcastChannel` API as usual.
This uses the polyfill, so the code can use the `BroadcastChannel` API as usual.

```typescript
import { createBroadcastChannel } from "https://deno.land/x/websocket_broadcastchannel/mod.ts";
import "https://deno.land/x/websocket_broadcastchannel/polyfill.ts";

const pid = Deno.pid;
const pidLastDigit = pid % 10;
Expand All @@ -77,11 +95,11 @@ const log = (s: string, ...args: unknown[]) => {
log("run this in multiple terminals on the same host, to see it work");

log("starting...");
const testChannel = createBroadcastChannel("test");
const testChannel = new BroadcastChannel("test");
log("testChannel.constructor.name", testChannel.constructor.name);

testChannel.onmessage = (event: MessageEvent<unknown>) => {
log("onmessage event.data =", event.data);
testChannel.onmessage = (event: Event) => {
log("onmessage event.data =", (event as MessageEvent).data);
};

testChannel.onmessageerror = (event: Event) => {
Expand All @@ -108,8 +126,7 @@ deno run \
### Server example from Deno Deploy docs

This is the example from Deno Deploy's documentation page for BroadcastChannel,
but now using this module's `await createBroadcastChannel(name)` instead of the
built-in `new BroadcastChannel(name)`.
but now with the addition of this module's polyfill.

Original:

Expand All @@ -118,17 +135,17 @@ https://deno.com/deploy/docs/runtime-broadcast-channel#example
Adapted to use this module:

```typescript
import "https://deno.land/x/websocket_broadcastchannel/polyfill.ts";
import { serve } from "https://deno.land/std@0.194.0/http/server.ts";
import { createBroadcastChannel } from "https://deno.land/x/websocket_broadcastchannel/mod.ts";

const messages: string[] = [];
// Create a new broadcast channel named earth.
const channel = createBroadcastChannel("earth");
const channel = new BroadcastChannel("earth");
// Set onmessage event handler.
channel.onmessage = (event: MessageEvent) => {
channel.onmessage = (event: Event) => {
// Update the local state when other instances
// send us a new message.
messages.push(event.data);
messages.push((event as MessageEvent).data);
};

function handler(req: Request): Response {
Expand Down Expand Up @@ -170,15 +187,12 @@ serve(handler, { port: parseInt(Deno.env.get("PORT") ?? "8080", 10) });
An example chat application, that you can run in several terminals on the same
host, and see the messages broadcast between them.

This uses the
[createBroadcastChannel](https://deno.land/x/websocket_broadcastchannel/mod.ts?s=createBroadcastChannel)
function to create the relevant `BroadcastChannel` object, and then uses the
`BroadcastChannel` API as usual.
This also uses the polyfill, so the code can use the `BroadcastChannel` API as
usual.

```typescript
import "https://deno.land/x/websocket_broadcastchannel/polyfill.ts";
import {
BroadcastChannelIsh,
createBroadcastChannel,
Logger,
logger,
WebSocketBroadcastChannel,
Expand All @@ -191,10 +205,9 @@ const log: Logger = logger(import.meta.url);
*/
async function main() {
log("Starting...");
const chat: BroadcastChannelIsh = createBroadcastChannel(
"chat",
);
const chat: BroadcastChannel = new BroadcastChannel("chat");

chat.onmessage;
if (chat instanceof WebSocketBroadcastChannel) {
console.error(`
===============================================================================
Expand Down
8 changes: 4 additions & 4 deletions examples/broadcast.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env -S deno run --allow-net --watch
import { createBroadcastChannel } from "../mod.ts";
import "../polyfill.ts";

const pid = Deno.pid;
const pidLastDigit = pid % 10;
Expand All @@ -12,11 +12,11 @@ const log = (s: string, ...args: unknown[]) => {
log("run this in multiple terminals on the same host, to see it work");

log("starting...");
const testChannel = createBroadcastChannel("test");
const testChannel = new BroadcastChannel("test");
log("testChannel.constructor.name", testChannel.constructor.name);

testChannel.onmessage = (event: MessageEvent<unknown>) => {
log("onmessage event.data =", event.data);
testChannel.onmessage = (event: Event) => {
log("onmessage event.data =", (event as MessageEvent).data);
};

testChannel.onmessageerror = (event: Event) => {
Expand Down
14 changes: 4 additions & 10 deletions examples/chat.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
#!/usr/bin/env -S deno run --allow-net --allow-env=DEBUG
import {
BroadcastChannelIsh,
createBroadcastChannel,
Logger,
logger,
WebSocketBroadcastChannel,
} from "../mod.ts";
import "../polyfill.ts";
import { Logger, logger, WebSocketBroadcastChannel } from "../mod.ts";

const log: Logger = logger(import.meta.url);

Expand All @@ -14,10 +9,9 @@ const log: Logger = logger(import.meta.url);
*/
async function main() {
log("Starting...");
const chat: BroadcastChannelIsh = createBroadcastChannel(
"chat",
);
const chat: BroadcastChannel = new BroadcastChannel("chat");

chat.onmessage;
if (chat instanceof WebSocketBroadcastChannel) {
console.error(`
===============================================================================
Expand Down
8 changes: 4 additions & 4 deletions examples/server-example.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#!/usr/bin/env -S deno run --allow-net --allow-env=PORT --watch
import "../polyfill.ts";
import { serve } from "https://deno.land/std@0.194.0/http/server.ts";
import { createBroadcastChannel } from "../mod.ts";

const messages: string[] = [];
// Create a new broadcast channel named earth.
const channel = createBroadcastChannel("earth");
const channel = new BroadcastChannel("earth");
// Set onmessage event handler.
channel.onmessage = (event: MessageEvent) => {
channel.onmessage = (event: Event) => {
// Update the local state when other instances
// send us a new message.
messages.push(event.data);
messages.push((event as MessageEvent).data);
};

function handler(req: Request): Response {
Expand Down
11 changes: 9 additions & 2 deletions polyfill.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { polyfillBroadcastChannel, WebSocketBroadcastChannel } from "./mod.ts";
// noinspection JSAnnotator,ES6ConvertVarToLetConst

/**
* @module polyfill
*
* This module polyfills the {@link BroadcastChannel} API, where not available.
*
* If already available, such as on Deno Deploy, it does nothing.
* If `BroadcastChannel` is already available, such as on Deno Deploy, this has no effect.
*/

import {
BroadcastChannelIsh,
polyfillBroadcastChannel,
WebSocketBroadcastChannel,
} from "./mod.ts";

declare global {
// deno-lint-ignore ban-ts-comment
// @ts-ignore
// deno-lint-ignore no-var
var BroadcastChannel = WebSocketBroadcastChannel;
type BroadcastChannel = BroadcastChannelIsh;
}

polyfillBroadcastChannel();
42 changes: 27 additions & 15 deletions readme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

An implementation of
[BroadcastChannel](https://developer.mozilla.org/docs/Web/API/BroadcastChannel)
for Deno, that uses
for Deno CLI, that uses
[WebSocket](https://developer.mozilla.org/docs/Web/API/WebSocket)s to
communicate between processes on the same host.

Expand All @@ -17,7 +17,8 @@ BroadcastChannel, will let you do so.

(At least until Deno will
[Support cross process BroadcastChannel #10750](https://github.com/denoland/deno/issues/10750)
in the `deno` CLI itself.)
in the `deno` CLI itself, which is planned, but blocked on
[an upstream issue](https://github.com/tokio-rs/mio/pull/1667).)

## Requirements

Expand All @@ -37,10 +38,27 @@ For specifics on what this module `export`s, see the auto-generated API docs at

## Example usage

Instead of using the built-in `BroadcastChannel` constructor, use this module's
`createBroadcastChannel(name)` function.
### With BroadcastChannel polyfill

It will either:
The easiest way to use this module, is to use the included polyfill.

Import it as early as possible in your code, before any other imports that may
use `BroadcastChannel`.

```typescript
"@@include(../examples/polyfill.ts)";
```

The polyfill does nothing if `BroadcastChannel` is already defined (on Deno
Deploy), and otherwise defines a global `BroadcastChannel` to use this module's
implementation.

### Without polyfill

For finer control, you may use the `createBroadcastChannel(name)` function,
instead of `new BroadcastChannel(name)` via the polyfill.

Calling the `createBroadcastChannel(name)` function will either:

- return a `BroadcastChannel` object if available (when running in Deno Deploy),
or
Expand All @@ -55,10 +73,7 @@ It will either:
A small example, that you can run in several terminals on the same host, and see
messages broadcast between them.

This uses this module's
[createBroadcastChannel(name)](https://deno.land/x/websocket_broadcastchannel/mod.ts?s=createBroadcastChannel)
function to create the relevant `BroadcastChannel` object, and then uses the
`BroadcastChannel` API as usual.
This uses the polyfill, so the code can use the `BroadcastChannel` API as usual.

```typescript
"@@include(../examples/broadcast.ts)";
Expand All @@ -76,8 +91,7 @@ deno run \
### Server example from Deno Deploy docs

This is the example from Deno Deploy's documentation page for BroadcastChannel,
but now using this module's `await createBroadcastChannel(name)` instead of the
built-in `new BroadcastChannel(name)`.
but now with the addition of this module's polyfill.

Original:

Expand All @@ -94,10 +108,8 @@ Adapted to use this module:
An example chat application, that you can run in several terminals on the same
host, and see the messages broadcast between them.

This uses the
[createBroadcastChannel](https://deno.land/x/websocket_broadcastchannel/mod.ts?s=createBroadcastChannel)
function to create the relevant `BroadcastChannel` object, and then uses the
`BroadcastChannel` API as usual.
This also uses the polyfill, so the code can use the `BroadcastChannel` API as
usual.

```typescript
"@@include(../examples/chat.ts)";
Expand Down
12 changes: 7 additions & 5 deletions readme/generate-readme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,18 @@ function processLineForImport(
publishUrl: string,
): (line: string) => string[] {
return (line: string): string[] => {
const match = line.match(/\sfrom\s+"(\..*)"/);
const importRegex = /((\sfrom|\bimport)\s+)"(\..*)"/;
const match: string[] | null = line.match(importRegex);
if (match) {
const importPath = match[1];
const importFrom = match[1];
const importPath = match[3];
const step1: string =
(new URL(importPath, `file://${inputFilePath}`)).pathname;
const gitRoot = (new URL("../", import.meta.url)).pathname;
const gitRoot: string = (new URL("../", import.meta.url)).pathname;
const step2: string = relative(gitRoot, step1);
return [line.replace(
/\sfrom\s+"(\..*)"/,
` from "${publishUrl}/${step2}"`,
importRegex,
`${importFrom}"${publishUrl}/${step2}"`,
)];
}
return [line];
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { WebSocketBroadcastChannel } from "./web-socket-broadcast-channel.ts";
*/
export interface BroadcastChannelIsh extends EventTarget {
readonly name: string;
onmessage: ((ev: MessageEvent) => void) | null;
onmessage: ((ev: Event) => void) | null;
onmessageerror: ((ev: Event) => void) | null;
postMessage(message: unknown): void;
close(): void;
Expand Down
4 changes: 2 additions & 2 deletions test/one-channel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env -S deno run --allow-net --allow-env
import "../polyfill.ts";
import { parse } from "https://deno.land/std@0.194.0/flags/mod.ts";
import { createBroadcastChannel } from "../mod.ts";
import { deferred } from "https://deno.land/std@0.194.0/async/deferred.ts";
import { s, sleep, ss } from "../src/fn.ts";
import { CommandFailureError } from "https://deno.land/x/run_simple@2.1.0/src/run.ts";
Expand All @@ -24,7 +24,7 @@ async function main(channelName: string, expectedCount: number) {
}, TOTAL_TIMEOUT);
void closed.then(() => clearTimeout(timeout));

const bc = createBroadcastChannel(channelName);
const bc = new BroadcastChannel(channelName);
console.error(`bc.name: ${s(bc.name)}`);
bc.addEventListener("close", () => {
console.error("bc closed");
Expand Down
Loading

0 comments on commit 69394b8

Please sign in to comment.