first commit
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# transport/native
|
||||
|
||||
## Purpose
|
||||
|
||||
`nativeChannelFactory` is a thin adapter that exposes the global `BroadcastChannel`
|
||||
constructor as a `ChannelLike`. Use this in any environment where the
|
||||
native API is available — every modern browser, Bun, and recent Node (with
|
||||
the `BroadcastChannel` global). The companion helper
|
||||
`isNativeBroadcastChannelAvailable()` is a one-line feature detect so callers
|
||||
can branch between the native transport and the `StorageLike`-backed
|
||||
fallback at runtime without try/catching around constructor lookups.
|
||||
|
||||
The adapter exists to fix the upstream "addEventListener(event: any)" smell:
|
||||
the native `BroadcastChannel` already hands back `MessageEvent` objects, and
|
||||
the wrapper preserves that static type in the `ChannelLike` signature. The
|
||||
surface never lets `any` leak from this code path.
|
||||
|
||||
## Features
|
||||
|
||||
- Zero-cost wrapper around the native `BroadcastChannel`.
|
||||
- Statically-typed `(event: MessageEvent) => void` listener forwarding.
|
||||
- `isNativeBroadcastChannelAvailable()` feature detect.
|
||||
- Sideeffect-free — `nativeChannelFactory` only constructs `BroadcastChannel` when invoked.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
nativeChannelFactory,
|
||||
TypedBroadcastChannel,
|
||||
} from "@suaveplan/broadcast-channel";
|
||||
|
||||
const channel = new TypedBroadcastChannel({
|
||||
config: { name: "app-bus" },
|
||||
factory: nativeChannelFactory,
|
||||
});
|
||||
channel.open();
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
createLocalStorageChannelFactory,
|
||||
isNativeBroadcastChannelAvailable,
|
||||
nativeChannelFactory,
|
||||
TypedBroadcastChannel,
|
||||
} from "@suaveplan/broadcast-channel";
|
||||
import type { StorageLike } from "@suaveplan/types";
|
||||
declare const storage: StorageLike;
|
||||
|
||||
const channel = new TypedBroadcastChannel({
|
||||
config: { name: "app-bus" },
|
||||
factory: isNativeBroadcastChannelAvailable()
|
||||
? nativeChannelFactory
|
||||
: createLocalStorageChannelFactory(storage),
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `const nativeChannelFactory: ChannelFactory` — `(name) => ChannelLike` wrapping `new BroadcastChannel(name)`.
|
||||
- `function isNativeBroadcastChannelAvailable(): boolean` — returns `true` if `globalThis.BroadcastChannel` is a function.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The wrapper does not extend `BroadcastChannel` directly because the suaveplan
|
||||
`ChannelLike` interface narrows `addEventListener` to a single literal type
|
||||
(`"message"`) — extending the host type would re-introduce the overloaded
|
||||
union the original surface carried and force callers to handle event types
|
||||
the channel never delivers (`messageerror`). Forwarding through a small
|
||||
adapter keeps the public type small and prevents accidental binding of the
|
||||
`messageerror` event, which the channel's leader-election and presence
|
||||
machinery is not designed to react to. The feature-detect helper checks for
|
||||
`typeof globalThis.BroadcastChannel === "function"` rather than `"undefined"
|
||||
!== typeof BroadcastChannel`: the literal-`function` check sidesteps the
|
||||
edge case where a host puts a non-callable stub on the global (some
|
||||
extension sandboxes do this) and forces the caller into the fallback path.
|
||||
Reference in New Issue
Block a user