# `Portals.SDK`
[🔗](https://github.com/Ziinc/portals/blob/v0.1.0/lib/portals/sdk.ex#L1)

The contract every `portals_<language>` package implements.

Core `portals` ships no worker SDKs. Each supported language lives in its
own Hex package (`portals_python`, `portals_ruby`, `portals_javascript`,
`portals_php`, `portals_java`, `portals_go`) that bundles its SDK under
`priv/` and exposes a module implementing this behaviour:

  * `c:sdk_path/0` — where the bundled SDK lives on disk. It is resolved
    through `Application.app_dir/2`, so it is valid under `mix run`, in
    tests and inside a `mix release`.
  * `c:worker_opts/1` — expands language-specific options (a script, a
    main class, a binary) into the generic `:command`/`:args`/`:env`
    options understood by `Portals.start_worker/1` and
    `Portals.start_pool/1`, including whatever puts the SDK on that
    runtime's import path. Every other option passes through untouched.

Every package also sets `PORTALS_SDK_PATH` in the worker's environment,
as an escape hatch for scripts that need to locate the SDK themselves.

All packages are released in lockstep with `portals`, so a worker SDK
always speaks the protocol version the BEAM expects.

# `sdk_path`

```elixir
@callback sdk_path() :: Path.t()
```

Absolute path to the SDK bundled in this package's `priv/` directory.

# `worker_opts`

```elixir
@callback worker_opts(keyword()) :: keyword()
```

Expand language-specific options into `Portals.start_worker/1` options.

# `languages`

```elixir
@spec languages() :: %{required(String.t()) =&gt; {module(), atom()}}
```

The supported languages and the package that provides each one.

    iex> Portals.SDK.languages()["python"]
    {Portals.Python, :portals_python}

# `module!`

```elixir
@spec module!(String.t()) :: module()
```

The `Portals.SDK` module for `language`, raising with installation
instructions when its package is not a dependency of the current project.

---

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