Releases: bots-garden/capsule
v0.3.2 🤗 [WASM I/O 2023]
Merge of PR made by @evacchi #225
- updates wazero to 1.0.0-rc.2
- changes for wazero 1.0.0-pre.9
Capsule is now twice as fast 🚀
Thanks a lot @evacchi
v0.3.1 🐊 [Tampa Bay]
Dependencies updates: wazero to 1.0.0-pre.8 | Thank you to @evacchi
v0.3.0 🎄 [Christmas tree]
Refactoring (Capsule is at least 4 times faster than the previous version).
v0.2.9 🦜 [parrot]
📦 updates modules for v0.2.9
v0.2.8 🦤 [dodo]
v0.2.7 🦚 [peacock]
The fall version 🍁
- The FaaS components are externalized; now, this project is only for the Capsule Runner
- "Scratch" Docker image (18.5M) to easily use and deploy the Capsule Runner (https://github.com/bots-garden/capsule-docker-image)
- cabu (or capsule-builder) (https://github.com/bots-garden/capsule-function-builder): a CLI using a specific Docker image allowing:
- the creation of a wasm function project (from templates)
- the build of the wasm function without installing anything (TinyGo and Golang compilers are embedded in the image) (https://github.com/bots-garden/capsule-function-builder)
The Docker image of Capsule will follow the same versioning.
Install Capsule
CAPSULE_VERSION="v0.2.7"
wget -O - https://raw.githubusercontent.com/bots-garden/capsule/${CAPSULE_VERSION}/install-capsule-launcher.sh| bash
The script will install Capsule in
$HOME/.local/bin
🖐 On macOS:
- create the
$HOME/.local/bin
directory - add it to your path:
export CAPSULE_PATH="$HOME/.local" export PATH="$CAPSULE_PATH/bin:$PATH"
if you want to install Capsule somewhere else, override the
CAPSULE_PATH
variable (default value:CAPSULE_PATH="$HOME/.local/bin"
)
Install Capsule Builder (cabu)
CAPSULE_BUILDER_VERSION="v0.0.1"
wget -O - https://raw.githubusercontent.com/bots-garden/capsule-function-builder/${CAPSULE_BUILDER_VERSION}/install-capsule-builder.sh | bash
v0.2.6 🐝 [Bee]
- #175 wazero: updates to 1.0.0-pre.2 by @codefromthecrypt 🙏
- a first logo/mascot
v0.2.5 🦖 [T-Rex] MQTT
This new version brings MQTT support. A big thank you to @py4mac ✨
You can now use Capsule as an MQTT subscriber:
package main
import (
hf "github.com/bots-garden/capsule/capsulemodule/hostfunctions"
)
func main() {
hf.OnMqttMessage(Handle)
}
func Handle(params []string) {
hf.Log("👋 on topic: " + hf.MqttGetTopic() + ", 🎉 message" + params[0])
_, err := hf.MqttPublish("topic/reply", "it's a wasm module here")
if err != nil {
hf.Log("😡 ouch something bad is happening")
hf.Log(err.Error())
}
}
# the topic is defined when launching the capsule launcher
capsule \
-wasm=./hello.wasm \
-mode=mqtt \
-mqttsrv=127.0.0.1:1883 \
-topic=topic/sensor0 \
-clientId=sensor
And you can use Capsule as an MQTT publisher:
package main
import (
"errors"
hf "github.com/bots-garden/capsule/capsulemodule/hostfunctions"
"strings"
)
func main() {
hf.SetHandle(Handle)
}
func Handle(params []string) (string, error) {
var errs []string
// a new connection is created at every call/publish
_, err1stMsg := hf.MqttConnectPublish("127.0.0.1:1883", "sensor_id0", "topic/sensor0", "🖐 Hello from WASM with MQTT 💜")
_, err2ndMsg := hf.MqttConnectPublish("127.0.0.1:1883", "sensor_id0", "topic/sensor1", "👋 Hello World 🌍")
if err1stMsg != nil {
errs = append(errs, err1stMsg.Error())
}
if err2ndMsg != nil {
errs = append(errs, err2ndMsg.Error())
}
return "MQTT Rocks!", errors.New(strings.Join(errs, "|"))
}
capsule \
-wasm=./hello.wasm \
-mode=cli
v0.2.4 🦎 [lizard] "flatjson"
Handling Json with TinyGo is not straight forward (but not impossible).
If your use case is very simple (a Json string without nested object or array) you can use:
flatjson.StrToMap(flatJsonStr string) map[string]interface{}
: get a flat json string (no nested obj) and return a mapflatjson.MapToStr(jsonMap map[string]interface{}) string
: get a flat json map and return a json string
Example:
package main
import (
"github.com/bots-garden/capsule/capsulemodule/flatjson"
hf "github.com/bots-garden/capsule/capsulemodule/hostfunctions"
"strconv"
)
func main() {
hf.SetHandleHttp(Handle)
}
func Handle(request hf.Request) (response hf.Response, errResp error) {
jsonMap := flatjson.StrToMap(request.Body)
author := jsonMap["author"].(string)
age := jsonMap["age"].(int)
weight := jsonMap["weight"].(float64)
isHuman := jsonMap["human"].(bool)
message := jsonMap["message"].(string)
hf.Log("👋 " + message + " by " + author + " 😄")
hf.Log("👋 age: " + strconv.Itoa(age))
hf.Log("👋 weight: " + strconv.FormatFloat(weight, 'f', 6, 64))
if isHuman {
hf.Log("I'm not a 🤖")
}
headersResp := map[string]string{
"Content-Type": "application/json; charset=utf-8",
}
responseMap := map[string]interface{}{
"message": "👋 hey! What's up?",
"author": "Bob",
}
return hf.Response{Body: flatjson.MapToStr(responseMap), Headers: headersResp}, nil
}
Call the function:
curl -v -X POST \
http://localhost:7070 \
-H 'content-type: application/json; charset=utf-8' \
-d '{"message": "TinyGo 💚💜 wasm", "author": "@k33g", "text":"this is a text", "age":42, "human": true, "weight": 100.5}'
v0.2.3 🐢 [turtle]
- Gardening with a part of the code
- Add Nats functions:
NatsConnectRequest
&NatsReply
Request and Reply
A NATS "publisher" can make a request to a NATS "subscriber" and wait for an answer
package main
import (
"errors"
hf "github.com/bots-garden/capsule/capsulemodule/hostfunctions"
"strings"
)
func main() {
hf.SetHandle(Handle)
}
func Handle(params []string) (string, error) {
// Publish and wait for an answer; 1 is the timeout in seconds
res, err := hf.NatsConnectRequest("nats.devsecops.fun:4222", "notify", "👋 Hello World 🌍", 1)
if err != nil {
hf.Log("🔴" + err.Error())
} else {
// Display the answer
hf.Log("🔵" + res)
}
return "NATS Rocks!", err
}
A NATS "subscriber" can reply to a request received on its subject
package main
import (
hf "github.com/bots-garden/capsule/capsulemodule/hostfunctions"
)
func main() {
hf.OnNatsMessage(Handle)
}
func Handle(params []string) {
hf.Log("Message on subject: " + hf.NatsGetSubject() + ", 🎉 message: " + params[0])
// reply to the message on the current subject; 10 is the timeout in seconds
_, _ = hf.NatsReply("Hey! What's up", 10)
}