# `Boam.JS`

Helpers for generating JavaScript shim code around the `beam.call(...)` bridge.

The main entrypoint is `export_prelude/1`, which takes a nested export tree and
returns JavaScript source that installs functions on `globalThis`.

This is useful in two modes:

  * pass the generated string through `prelude:` when you want manual control
    over dispatching
  * let `Boam.Runtime` do the same work automatically with `expose:`

## Examples

Generate a manual prelude:

```elixir
prelude =
  Boam.JS.export_prelude(%{
    console: %{
      log: true,
      error: {:dispatch, "logger.error"}
    }
  })
```

That produces JavaScript equivalent to:

```javascript
if (globalThis["console"] == null) { globalThis["console"] = {}; }
globalThis["console"]["log"] = (...args) => beam.call("console.log", ...args);
globalThis["console"]["error"] = (...args) => beam.call("logger.error", ...args);
```

# `export_tree`

```elixir
@type export_tree() ::
  %{optional(path_key()) =&gt; export_tree() | leaf()}
  | keyword(export_tree() | leaf())
```

# `leaf`

```elixir
@type leaf() ::
  true
  | Boam.Dispatcher.handler()
  | {:dispatch, atom() | String.t()}
  | {:dispatch, atom() | String.t(), Boam.Dispatcher.handler()}
```

Leaf spec for a generated JavaScript function.

  * `true` derives the dispatch name from the nested path
  * a `Dispatcher.handler/0` also derives the dispatch name from the path
  * `{:dispatch, name}` generates a shim without attaching a handler
  * `{:dispatch, name, handler}` uses a custom dispatch name and handler

# `path_key`

```elixir
@type path_key() :: atom() | String.t()
```

# `export_prelude`

```elixir
@spec export_prelude(export_tree()) :: String.t()
```

Builds a JavaScript prelude that exposes nested shim functions on `globalThis`.

Leaf dispatch names default to the dot-joined path. For example:

```elixir
Boam.JS.export_prelude(%{
  console: %{
    log: true
  }
})
```

defines `globalThis.console.log = (...args) => beam.call("console.log", ...args)`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
