Skip to content

henomis/pluggo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”Œ Pluggo

A simple HTTP-based plugin system for Go.

Build Status GoDoc Go Report Card GitHub release

πŸš€ Features

  • πŸš€ Simple Plugin System: Easy-to-use API for creating and managing plugins
  • πŸ”’ Type Safety: Generic-based functions with compile-time type checking
  • 🌐 HTTP Communication: Reliable plugin communication over HTTP
  • πŸ“‹ Schema Validation: Automatic JSON schema generation and validation
  • πŸ”„ Dynamic Loading: Load and execute plugins at runtime
  • ⚑ Performance: Minimal overhead with efficient execution
  • πŸ₯ Health Checks: Built-in health monitoring for plugin processes

πŸ“¦ Installation

go get github.com/henomis/pluggo

🎯 Quick Start

Creating a Plugin

Create a plugin that implements a simple greeting function:

plugin/plugin.go

package main

import (
    "context"
    "github.com/henomis/pluggo"
)

type Input struct {
    Name string `json:"name" jsonschema:"minLength=3"`
}

type Output struct {
    Greeting string `json:"greeting"`
}

func Hello(ctx context.Context, in *Input) (*Output, error) {
    return &Output{Greeting: "Hello, " + in.Name + "!"}, nil
}

func main() {
    p := pluggo.NewPlugin()
    
    // Create validator for input validation
    v, err := pluggo.NewValidator(&Input{})
    if err != nil {
        panic(err)
    }
    
    // Register the function
    p.AddFunction("hello", pluggo.NewFunctionHandler(Hello, v).Handler())
    
    // Start the plugin server
    err = p.Start()
    if err != nil {
        panic(err)
    }
}

Build the plugin:

go build -o plugin plugin.go

Using the Plugin

main.go

package main

import (
    "context"
    "fmt"
    "github.com/henomis/pluggo"
)

type Input struct {
    Name string `json:"name"`
}

type Output struct {
    Greeting string `json:"greeting"`
}

func main() {
    // Create client and load plugin
    client := pluggo.New("./plugin/plugin")
    err := client.Open(context.Background())
    if err != nil {
        panic(err)
    }
    defer client.Close()
    
    // Create type-safe function
    hello := pluggo.NewFunction[Input, Output]("hello", client.Connection())
    
    // Call the function
    result, err := hello.Call(&Input{Name: "World"})
    if err != nil {
        panic(err)
    }
    
    fmt.Println(result.Greeting) // Output: Hello, World!
}

πŸ“š Examples

The repository includes several examples in the examples/ directory

πŸ—οΈ Architecture

Pluggo uses an HTTP-based architecture where:

  1. πŸš€ Plugin Launch: Client launches plugin as separate process
  2. πŸ“‘ HTTP Communication: Plugin starts HTTP server and communicates port via stdout
  3. πŸ” Discovery: Client discovers available functions via /_schemas endpoint
  4. πŸ₯ Health Monitoring: Built-in health checks via /_healthz endpoint
  5. ⚑ Function Execution: Type-safe function calls via HTTP POST requests
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    HTTP     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client    │◄───────────►│   Plugin    β”‚
β”‚             β”‚             β”‚             β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚             β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚Function β”‚ β”‚             β”‚ β”‚Handler  β”‚ β”‚
β”‚ β”‚         β”‚ │────────────►│ β”‚         β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚             β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ API Reference

Plugin Server

Creating a Plugin

p := pluggo.NewPlugin()

Adding Functions

p.AddFunction(name string, handler http.HandlerFunc)

Starting the Server

err := p.Start()

Client

Creating a Client

client := pluggo.New(pluginPath string)

Opening Connection

err := client.Open(ctx context.Context)

Getting Available Functions

schemas, err := client.Schemas()

Type-Safe Functions

Creating a Function

fn := pluggo.NewFunction[InputType, OutputType](name string, connection *pluggo.Connection)

Calling a Function

result, err := fn.Call(input *InputType)

Getting Function Schema

schema, err := fn.Schema()

πŸ›‘οΈ Input Validation

Pluggo supports automatic input validation using JSON Schema tags:

type Input struct {
    Name  string `json:"name" jsonschema:"minLength=3,maxLength=50"`
    Age   int    `json:"age" jsonschema:"minimum=0,maximum=120"`
    Email string `json:"email" jsonschema:"format=email"`
}

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Built with Go's native HTTP server for maximum performance
  • Uses JSON Schema for robust input validation
  • Inspired by modern microservices architecture patterns

Made with ❀️ by henomis

About

A simple HTTP-based plugin system for Go

Resources

License

Stars

Watchers

Forks

Languages