README.md

# Extism

Extism Host SDK for Elixir

> *Note*: This houses the 1.0 pre-release version of the Elixir SDK. We may push breaking changes in new versions until will hit 1.0 in December, 2023. But it's currently the best place to start a new integration and we welcome any feedback.

## Docs

Read the [docs on hexdocs.pm](https://hexdocs.pm/extism/).

## Installation

You can find this package on hex.pm [![hex.pm](https://img.shields.io/hexpm/v/extism.svg)](https://hex.pm/packages/extism)

```elixir
def deps do
  [
    {:extism, "1.0.0-rc2"}
  ]
end
```

> **Note**: You do not need to install the Extism Runtime shared object, but you will need a rust toolchain installed to build this package. See [Install Rust](https://www.rust-lang.org/tools/install) to install for your platform.

## Getting Started

This guide should walk you through some of the concepts in Extism and this Elixir library.

> *Note*: You should be able to follow this guide by copy pasting the code into `iex` using `iex -S mix`.

### Creating A Plug-in

The primary concept in Extism is the [plug-in](https://extism.org/docs/concepts/plug-in). You can think of a plug-in as a code module stored in a `.wasm` file.

Since you may not have an Extism plug-in on hand to test, let's load a demo plug-in from the web:

```elixir
url = "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm"
manifest = %{wasm: [%{url: url}]}
{:ok, plugin} = Extism.Plugin.new(manifest, false)
```

> **Note**: See [the Manifest docs](https://extism.org/docs/concepts/manifest) as it has a rich schema and a lot of options.

### Calling A Plug-in's Exports

This plug-in was written in Rust and it does one thing, it counts vowels in a string. As such, it exposes one "export" function: `count_vowels`. We can call exports using [Extism.Plugin#call/3](https://hexdocs.pm/extism/Extism.Plugin.html#call/3):

```elixir
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "Hello, World!")
# => {"count": 3, "total": 3, "vowels": "aeiouAEIOU"}
```

All exports have a simple interface of bytes-in and bytes-out. This plug-in happens to take a string and return a JSON encoded string with a report of results.

### Plug-in State

Plug-ins may be stateful or stateless. Plug-ins can maintain state b/w calls by the use of variables. Our count vowels plug-in remembers the total number of vowels it's ever counted in the "total" key in the result. You can see this by making subsequent calls to the export:

```elixir
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "Hello, World!")
# => {"count": 3, "total": 6, "vowels": "aeiouAEIOU"}
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "Hello, World!")
# => {"count": 3, "total": 9, "vowels": "aeiouAEIOU"}
```

These variables will persist until this plug-in is freed or you initialize a new one.

### Configuration

> TODO: Implement config

Plug-ins may optionally take a configuration object. This is a static way to configure the plug-in. Our count-vowels plugin takes an optional configuration to change out which characters are considered vowels. Example:

```elixir
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "Yellow, World!")
# => {"count": 3, "total": 3, "vowels": "aeiouAEIOU"}

{:ok, plugin} = Extism.Plugin.new(manifest, false, %{"vowels": "aeiouyAEIOUY"})
{:ok, output} = Extism.Plugin.call(plugin, "count_vowels", "Yellow, World!")
plugin.call("count_vowels", "Yellow, World!")
# => {"count": 4, "total": 4, "vowels": "aeiouAEIOUY"}
```

### Host Functions

We don't offer host function support in this library yet. If it is something you need, please [file an issue](https://github.com/extism/elixir-sdk/issues/new)!