extism 1.0.0.pre.rc.1 → 1.0.0.pre.rc.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +206 -191
- data/lib/extism/current_plugin.rb +30 -2
- data/lib/extism/host_environment.rb +16 -0
- data/lib/extism/plugin.rb +13 -0
- data/lib/extism/version.rb +5 -5
- metadata +2 -3
- data/example.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9de040945d856411394ee9e9631aeffdf7b89a6e1269788e823191a26c0e50a8
|
4
|
+
data.tar.gz: 9a588d3b134ee5e1d817d38bb4bd0b8abb92d48148c35d4b538870872dffafd3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a675e36bf299fbb2dc2457a35569ef491f0f6be308f7afe7e01603d83971fe6b7f8a23051bb385eb1de5a9be6948d8658128975aa3b183f02b54c9e0312abb58
|
7
|
+
data.tar.gz: '082c612825780d24869dd7a975adf67cf61f5a7e90b3c4b801cad6769ef69eb237e43621a118a95c6d376bc1d88e57fb0ba1f27519ffc31f52850a453c229865'
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,191 +1,206 @@
|
|
1
|
-
# Extism Ruby Host SDK
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
This repo
|
6
|
-
|
7
|
-
## Installation
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
```
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
```
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
```ruby
|
28
|
-
|
29
|
-
```
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
plugin.call("count_vowels", "Hello, World!")
|
70
|
-
# => {"count": 3, "total":
|
71
|
-
```
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
###
|
76
|
-
|
77
|
-
Plug-ins may
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
plugin
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
customer_id
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
#
|
161
|
-
puts "
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
1
|
+
# Extism Ruby Host SDK
|
2
|
+
|
3
|
+
This repo houses the ruby gem for integrating with the [Extism](https://extism.org/) runtime. Install this library into your host ruby applications to run Extism plug-ins.
|
4
|
+
|
5
|
+
> **Note**: This repo is 1.0 alpha version of the Ruby SDK and is a work in progress. We'd love any feedback you have on it, but consider using the supported ruby SDK in [extism/extism](https://github.com/extism/extism/tree/main/ruby) until we hit 1.0.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
### Install the Extism Runtime
|
10
|
+
|
11
|
+
You first need to install the Extism Runtime which is a native shared object that this library uses to load and run the Wasm code. You can [download the shared library directly from a release](https://github.com/extism/extism/releases) or use the [Extism CLI](https://github.com/extism/cli) to install it:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
sudo extism lib install latest
|
15
|
+
|
16
|
+
#=> Fetching https://github.com/extism/extism/releases/download/v0.5.2/libextism-aarch64-apple-darwin-v0.5.2.tar.gz
|
17
|
+
#=> Copying libextism.dylib to /usr/local/lib/libextism.dylib
|
18
|
+
#=> Copying extism.h to /usr/local/include/extism.h
|
19
|
+
```
|
20
|
+
|
21
|
+
> **Note**: This library has breaking changes and targets 1.0 of the runtime. For the time being, install the runtime from our nightly development builds on git: `sudo extism lib install --version git`
|
22
|
+
|
23
|
+
### Install the Rubygem
|
24
|
+
|
25
|
+
Add this library to your [Gemfile](https://bundler.io/):
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
gem 'extism', '1.0.0.pre.rc.2'
|
29
|
+
```
|
30
|
+
|
31
|
+
Or if installing on the system level:
|
32
|
+
|
33
|
+
```
|
34
|
+
gem install extism --pre
|
35
|
+
```
|
36
|
+
|
37
|
+
## Getting Started
|
38
|
+
|
39
|
+
> *Note*: You should be able to follow this guide by copy pasting the code into `irb`.
|
40
|
+
|
41
|
+
First you should require `"extism"`:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require "extism"
|
45
|
+
```
|
46
|
+
|
47
|
+
### Creating A Plug-in
|
48
|
+
|
49
|
+
The primary concept in Extism is the plug-in. You can think of a plug-in as a code module stored in a `.wasm` file. You can [learn more about plug-ins here](https://extism.org/concepts/plug-in).
|
50
|
+
|
51
|
+
You'll generally load the plug-in from disk, but for simplicity let's load a pre-built demo plug-in from the web:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
manifest = {
|
55
|
+
wasm: [
|
56
|
+
{ url: "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm" }
|
57
|
+
]
|
58
|
+
}
|
59
|
+
plugin = Extism::Plugin.new(manifest)
|
60
|
+
```
|
61
|
+
|
62
|
+
> **Note**: The schema for this manifest can be found here: [https://extism.org/docs/concepts/manifest/](https://extism.org/docs/concepts/manifest/)
|
63
|
+
|
64
|
+
### Calling A Plug-in's Exports
|
65
|
+
|
66
|
+
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](https://extism.github.io/ruby-sdk/Extism/Plugin.html#call-instance_method):
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
plugin.call("count_vowels", "Hello, World!")
|
70
|
+
# => {"count": 3, "total": 3, "vowels": "aeiouAEIOU"}
|
71
|
+
```
|
72
|
+
|
73
|
+
All exports have a simple interface of optional bytes in, and optional bytes out. This plug-in happens to take a string and return a JSON encoded string with a report of results.
|
74
|
+
|
75
|
+
### Plug-in State
|
76
|
+
|
77
|
+
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:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
plugin.call("count_vowels", "Hello, World!")
|
81
|
+
# => {"count": 3, "total": 6, "vowels": "aeiouAEIOU"}
|
82
|
+
plugin.call("count_vowels", "Hello, World!")
|
83
|
+
# => {"count": 3, "total": 9, "vowels": "aeiouAEIOU"}
|
84
|
+
```
|
85
|
+
|
86
|
+
These variables will persist until this plug-in is freed or you initialize a new one.
|
87
|
+
|
88
|
+
### Configuration
|
89
|
+
|
90
|
+
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:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
plugin = Extism::Plugin.new(manifest)
|
94
|
+
plugin.call("count_vowels", "Yellow, World!")
|
95
|
+
# => {"count": 3, "total": 3, "vowels": "aeiouAEIOU"}
|
96
|
+
|
97
|
+
plugin = Extism::Plugin.new(manifest, config: { vowels: "aeiouyAEIOUY" })
|
98
|
+
plugin.call("count_vowels", "Yellow, World!")
|
99
|
+
# => {"count": 4, "total": 4, "vowels": "aeiouAEIOUY"}
|
100
|
+
```
|
101
|
+
|
102
|
+
### Host Functions
|
103
|
+
|
104
|
+
Host functions allow us to grant new capabilities to our plug-ins from our application. They are simply some ruby methods you write which can be passed to and invoked from any language inside the plug-in.
|
105
|
+
|
106
|
+
> *Note*: Host functions can be a complicated topic. Please review this [concept doc](https://extism.org/docs/concepts/host-functions) if you are unsure how they work.
|
107
|
+
|
108
|
+
### Host Functions Example
|
109
|
+
|
110
|
+
We've created a contrived, but familiar example to illustrate this. Suppose you are a stripe-like payments platform.
|
111
|
+
When a [charge.succeeded](https://stripe.com/docs/api/events/types#event_types-charge.succeeded) event occurs, we will call the `on_charge_succeeded` function on our merchant's plug-in and let them decide what to do with it. Here our merchant has some very specific requirements, if the account has spent more than $100, their currency is USD, and they have no credits on their account, it will add $10 credit to their account and then send them an email.
|
112
|
+
|
113
|
+
> *Note*: The source code for this is [here](https://github.com/extism/plugins/blob/main/store_credit/src/lib.rs) and is written in rust, but it could be written in any of our PDK languages.
|
114
|
+
|
115
|
+
First let's create the manifest for our plug-in like usual but load up the `store_credit` plug-in:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
manifest = {
|
119
|
+
wasm: [
|
120
|
+
{ url: "https://github.com/extism/plugins/releases/latest/download/store_credit.wasm" }
|
121
|
+
]
|
122
|
+
}
|
123
|
+
```
|
124
|
+
|
125
|
+
But, unlike our `count_vowels` plug-in, this plug-in expects you to provide host functions that satisfy our plug-in's imports.
|
126
|
+
|
127
|
+
In the ruby sdk, we have a concept for this called a [Host Environment](https://extism.github.io/ruby-sdk/Extism/HostEnvironment.html). An environment is just an object that responds to `host_functions` and returns an array of `Extism::Function`s. We want to expose two capabilities to our plugin, `add_credit(customer_id, amount)` which adds credit to an account and `send_email(customer_id, email)` which sends them an email.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
|
131
|
+
# This is global is just for demo purposes but would in
|
132
|
+
# reality be in a database or something
|
133
|
+
CUSTOMER = {
|
134
|
+
full_name: 'John Smith',
|
135
|
+
customer_id: 'abcd1234',
|
136
|
+
total_spend: {
|
137
|
+
currency: 'USD',
|
138
|
+
amount_in_cents: 20_000
|
139
|
+
},
|
140
|
+
credit: {
|
141
|
+
currency: 'USD',
|
142
|
+
amount_in_cents: 0
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
class MyEnvironment
|
147
|
+
include Extism::HostEnvironment
|
148
|
+
|
149
|
+
# we need to register each import that the plug-in expects and match the Wasm signature
|
150
|
+
# register_import takes the name, the param types, and the return types
|
151
|
+
register_import :add_credit, [Extism::ValType::I64, Extism::ValType::I64], [Extism::ValType::I64]
|
152
|
+
register_import :send_email, [Extism::ValType::I64, Extism::ValType::I64], []
|
153
|
+
|
154
|
+
def add_credit(plugin, inputs, outputs, _user_data)
|
155
|
+
# add_credit takes a string `customer_id` as the first parameter
|
156
|
+
customer_id = plugin.input_as_string(inputs.first)
|
157
|
+
# it takes an object `amount` { amount_in_cents: int, currency: string } as the second parameter
|
158
|
+
amount = plugin.input_as_json(inputs[1])
|
159
|
+
|
160
|
+
# we're just going to print it out and add to the CUSTOMER global
|
161
|
+
puts "Adding Credit #{amount} to customer #{customer_id}"
|
162
|
+
CUSTOMER[:credit][:amount_in_cents] += amount['amount_in_cents']
|
163
|
+
|
164
|
+
# add_credit returns a Json object with the new customer details
|
165
|
+
plugin.return_json(outputs.first, CUSTOMER)
|
166
|
+
end
|
167
|
+
|
168
|
+
def send_email(plugin, inputs, _outputs, _user_data)
|
169
|
+
# send_email takes a string `customer_id` as the first parameter
|
170
|
+
customer_id = plugin.input_as_string(inputs.first)
|
171
|
+
# it takes an object `email` { subject: string, body: string } as the second parameter
|
172
|
+
email = plugin.input_as_json(inputs[1])
|
173
|
+
|
174
|
+
# we'll just print it but you could imagine we'd put something
|
175
|
+
# in a database or call an internal api to send this email
|
176
|
+
puts "Sending email #{email} to customer #{customer_id}"
|
177
|
+
|
178
|
+
# it doesn't return anything
|
179
|
+
end
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
Now we just need to create a new host environment and pass it in when loading the plug-in. Here our environment initializer takes no arguments, but you could imagine putting some merchant specific instance variables in there:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
env = MyEnvironment.new
|
187
|
+
plugin = Extism::Plugin.new(manifest, environment: env)
|
188
|
+
```
|
189
|
+
|
190
|
+
Now we can invoke the event:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
event = {
|
194
|
+
event_type: 'charge.succeeded',
|
195
|
+
customer: CUSTOMER
|
196
|
+
}
|
197
|
+
result = plugin.call('on_charge_succeeded', JSON.generate(event))
|
198
|
+
```
|
199
|
+
|
200
|
+
This will print:
|
201
|
+
|
202
|
+
```
|
203
|
+
Adding Credit {"amount_in_cents"=>1000, "currency"=>"USD"} for customer abcd1234
|
204
|
+
Sending email {"subject"=>"A gift for you John Smith", "body"=>"You have received $10 in store credi
|
205
|
+
t!"} to customer abcd1234
|
206
|
+
```
|
@@ -16,6 +16,10 @@ module Extism
|
|
16
16
|
|
17
17
|
# Allocates a memory block in the plugin
|
18
18
|
#
|
19
|
+
# @example
|
20
|
+
# mem = current_plugin.alloc(1_024)
|
21
|
+
# mem.put_bytes(0, "Hello, World!")
|
22
|
+
#
|
19
23
|
# @param amount [Integer] The amount in bytes to allocate
|
20
24
|
# @return [Extism::Memory] The reference to the freshly allocated memory
|
21
25
|
def alloc(amount)
|
@@ -25,13 +29,21 @@ module Extism
|
|
25
29
|
|
26
30
|
# Frees the memory block
|
27
31
|
#
|
32
|
+
# @example
|
33
|
+
# mem = current_plugin.alloc(1_024)
|
34
|
+
# current_plugin.free(mem)
|
35
|
+
#
|
28
36
|
# @param memory [Extism::Memory] The memory object you wish to free
|
29
37
|
# @return [Extism::Memory] The reference to the freshly allocated memory
|
30
38
|
def free(memory)
|
31
39
|
LibExtism.extism_current_plugin_memory_free(@ptr, memory.offset)
|
32
40
|
end
|
33
41
|
|
34
|
-
# Gets the memory block at a given offset
|
42
|
+
# Gets the memory block at a given offset. Note: try to use input_* and output_* methods where possible.
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# mem = current_plugin.memory_at_offset(123456789)
|
46
|
+
# current_plugin.free(mem)
|
35
47
|
#
|
36
48
|
# @raise [Extism::Error] if memory block could not be found
|
37
49
|
#
|
@@ -48,6 +60,10 @@ module Extism
|
|
48
60
|
#
|
49
61
|
# @raise [Extism::Error] if memory block could not be found
|
50
62
|
#
|
63
|
+
# @example
|
64
|
+
# param1 = current_plugin.input_as_string(inputs.first)
|
65
|
+
# raise "Failed" unless param1 == "First param from plug-in host function call"
|
66
|
+
#
|
51
67
|
# @param input [Extism::Val] The input val from the host function
|
52
68
|
# @return [String] raw bytes as a string
|
53
69
|
def input_as_string(input)
|
@@ -57,10 +73,14 @@ module Extism
|
|
57
73
|
memory_ptr(mem).read_bytes(mem.len)
|
58
74
|
end
|
59
75
|
|
60
|
-
# Gets the input as a
|
76
|
+
# Gets the input as a JSON parsed Hash
|
61
77
|
#
|
62
78
|
# @raise [Extism::Error] if memory block could not be found
|
63
79
|
#
|
80
|
+
# @example
|
81
|
+
# param1 = current_plugin.input_as_json(inputs.first)
|
82
|
+
# raise "Failed" unless param1 == {hello: "world"}
|
83
|
+
#
|
64
84
|
# @param input [Extism::Val] The input val from the host function
|
65
85
|
# @return [Hash] The Hash object
|
66
86
|
def input_as_json(input)
|
@@ -73,6 +93,10 @@ module Extism
|
|
73
93
|
|
74
94
|
# Sets string to the return of the host function
|
75
95
|
#
|
96
|
+
# @example
|
97
|
+
# msg = "A string returned from the host function"
|
98
|
+
# current_plugin.output_string(outputs.first, msg)
|
99
|
+
#
|
76
100
|
# @raise [Extism::Error] if memory block could not be found
|
77
101
|
#
|
78
102
|
# @param output [Extism::Val] The output val from the host function
|
@@ -85,6 +109,10 @@ module Extism
|
|
85
109
|
|
86
110
|
# Sets json to the return of the host function
|
87
111
|
#
|
112
|
+
# @example
|
113
|
+
# msg = {hello: "world"}
|
114
|
+
# current_plugin.output_json(outputs.first, msg)
|
115
|
+
#
|
88
116
|
# @raise [Extism::Error] if memory block could not be found
|
89
117
|
#
|
90
118
|
# @param output [Extism::Val] The output val from the host function
|
@@ -1,4 +1,20 @@
|
|
1
1
|
module Extism
|
2
|
+
# Represents an "environment" that can be imported to a plug-in
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# class MyEnvironment
|
6
|
+
# include Extism::HostEnvironment
|
7
|
+
# # we need to register each import that the plug-in expects and match the Wasm signature
|
8
|
+
# # register_import takes the name, the param types, and the return types
|
9
|
+
# register_import :reflect, [Extism::ValType::I64], [Extism::ValType::I64]
|
10
|
+
#
|
11
|
+
# # reflect just takes a string from the plug-in and reflects it back in return
|
12
|
+
# def reflect(plugin, inputs, outputs, _user_data)
|
13
|
+
# msg = plugin.input_as_string(inputs.first)
|
14
|
+
# plugin.output_string(outputs.first, msg)
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
2
18
|
module HostEnvironment
|
3
19
|
def self.included(base)
|
4
20
|
base.extend ClassMethods
|
data/lib/extism/plugin.rb
CHANGED
@@ -4,6 +4,14 @@ module Extism
|
|
4
4
|
class Plugin
|
5
5
|
# Intialize a plugin
|
6
6
|
#
|
7
|
+
# @example
|
8
|
+
# manifest = {
|
9
|
+
# wasm: [
|
10
|
+
# { url: "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm" }
|
11
|
+
# ]
|
12
|
+
# }
|
13
|
+
# plugin = Extism::Plugin.new(manifest)
|
14
|
+
#
|
7
15
|
# @param wasm [Hash, String] The manifest as a Hash or WASM binary as a String. See https://extism.org/docs/concepts/manifest/.
|
8
16
|
# @param wasi [Boolean] Enable WASI support
|
9
17
|
# @param config [Hash] The plugin config
|
@@ -46,6 +54,11 @@ module Extism
|
|
46
54
|
|
47
55
|
# Call a function by name
|
48
56
|
#
|
57
|
+
# @example
|
58
|
+
# input = JSON.generate({hello: "world"})
|
59
|
+
# result = plugin.call("my_func", input)
|
60
|
+
# output = JSON.parse(result)
|
61
|
+
#
|
49
62
|
# @param name [String] The function name
|
50
63
|
# @param data [String] The input data for the function
|
51
64
|
# @return [String] The output from the function in String form
|
data/lib/extism/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Extism
|
4
|
-
VERSION = '1.0.0-rc.
|
5
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Extism
|
4
|
+
VERSION = '1.0.0-rc.2'
|
5
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extism
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.rc.
|
4
|
+
version: 1.0.0.pre.rc.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -38,7 +38,6 @@ files:
|
|
38
38
|
- Makefile
|
39
39
|
- README.md
|
40
40
|
- Rakefile
|
41
|
-
- example.rb
|
42
41
|
- lib/extism.rb
|
43
42
|
- lib/extism/current_plugin.rb
|
44
43
|
- lib/extism/host_environment.rb
|
data/example.rb
DELETED