This implements the a basic Elixir / Erlang host SDK. I still have some
work to do on it this weekend.
## Testing
* Pull down this branch
* In a different folder create a new elixir project:
`mix new extism_elixir_host && cd extism_elixir_host`
* Link to the local dependency by updating the `deps` in `mix.exs`:
```elixir
defp deps do
[
{:extism, path: "/Users/ben/Code/extism/elixir"}
]
end
```
* Run `mix deps.get`
* Run `mix deps.compile`, this should trigger the rust compilation in
the elixir lib depdency
* Run `iex -S mix` to start a REPL.
* Test happy path:
```elixir
iex(1)> manifest = %{ wasm: [ %{ path: "/Users/ben/code/extism/wasm/code.wasm" } ]}
%{wasm: [%{path: "/Users/ben/code/extism/wasm/code.wasm"}]}
iex(2)> {:ok, plugin} = Extism.Plugin.new(manifest)
{:ok,
%Extism.Plugin{
resource: 0,
reference: #Reference<0.1101693245.999030787.163527>
}}
iex(3)> {:ok, result} = Extism.Plugin.call(plugin, "count_vowels", "this is a test")
{:ok, "{\"count\": 4}"}
```
* Test the sad path:
```elixir
iex(1)> manifest = %{ wasm: [ %{ path: "/Users/ben/code/extism/wasm/code.wasmz" } ]}
%{wasm: [%{path: "/Users/ben/code/extism/wasm/code.wasmz"}]}
iex(2)> Extism.Plugin.new(manifest)
{:error, "Could not load plugin"}
iex(3)> manifest = %{ wasm: [ %{ pathe: "/Users/ben/code/extism/wasm/code.wasm" } ]}
%{wasm: [%{pathe: "/Users/ben/code/extism/wasm/code.wasm"}]}
iex(4)> Extism.Plugin.new(manifest)
{:error, "Could not parse manifest"}
```
* Some other functions you can use:
```elixir
iex(8)> Extism.Plugin.set_log_file(plugin, "/tmp/mylog.log", "debug")
:ok
iex(9)> Extism.Plugin.update(plugin, %{wasm: [%{path: "/Users/ben/Code/extism/wasm/code.wasm"}]}, true)
{:ok, true}
iex(10)> Extism.Plugin.has_function(plugin, "unknown")
false
iex(11)> Extism.Plugin.has_function(plugin, "count_vowels")
true
```
## Running unit tests
```
cd elixir/
mix do deps.get, deps.compile
mix test
```
- Adds `allowed_hosts` to the manifest
- If there are any `allowed_hosts` then `extism_http_request` checks to
make sure a URL's host is listed before performing the reques
- Adds `ExtismContext` instead of global `PLUGINS` registry
- Adds `extism_context_new`, `extism_context_free` and
`extism_context_reset`
- Requires updating nearly every SDK function to add context parameter
- Renames some SDK functions to follow better naming conventions
- `extism_plugin_register` -> `extism_plugin_new`
- `extism_output_get` -> `extism_plugin_output_data`
- `extism_output_length` -> `extism_plugin_output_length`
- `extism_call` -> `extism_plugin_call`
- Updates `extism_error` to return the context error when -1 issued for
the plug-in ID
- Adds `extism_plugin_free` to remove an existing plugin
- Updates SDKs to include these functions
- Updates SDK examples and comments
Co-authored-by: Steve Manuel <steve@dylib.so>
Adds a script to check which runtime API functions are not used in each host SDK. Provides a coverage report with percent of functions called in each SDK.
Co-authored-by: Steve Manuel <steve@dylib.so>