Uno is a lightweight, efficient microservices framework built on top of NATS, designed to simplify the development of distributed applications. It provides a clean and intuitive API for building scalable microservices with built-in monitoring, tracing, and observability features.
Uno is result of rethink and rework of NATS micro
framework, major additions are:
- Typed endpoints (automatic marshaling/unmarshaling)
- Interceptors
- Auto generated client
- Scaffolding (code generator)
- 🚀 Easy-to-use API for building NATS-based microservices
- 📊 Built-in Prometheus integration
- 🔍 OpenTelemetry integration for distributed tracing
- 🎯 Flexible endpoint routing and grouping
- 🔄 Automatic request handling and response management
- 🛠 Scaffolding and Client generation based on YAML service definition
- 🔌 Extensible through interceptors
- 🕒 Context support (deadlines)
Uno is currently in the alpha stage and is still under development. We welcome contributions and feedback to improve the framework.
go get github.com/appetito/uno
package main
import (
"github.com/appetito/uno"
"github.com/nats-io/nats.go"
)
func main() {
// Connect to NATS
nc, _ := nats.Connect(nats.DefaultURL)
// Create a new service
svc, _ := uno.AddService(nc, uno.Config{
Name: "my-service",
Version: "1.0.0",
})
// Add an endpoint
svc.AddEndpoint("hello", uno.HandlerFunc(func(req uno.Request) {
req.Respond([]byte("Hello, World!"))
}))
// Start the service
svc.ServeForever()
}
Run and call service with nats CLI:
nats req "hello" 'Hey'
Uno is compatible with NATS micro
tool:
nats micro list
nats micro info my-service
group := svc.AddGroup("users")
group.AddEndpoint("add", uno.HandlerFunc(AddUserHandler))
group.AddEndpoint("list", uno.HandlerFunc(ListUsersHandler))
Type-safe request handling with automatic marshaling/unmarshaling:
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type CreateUserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
svc.AddEndpoint("create-user", uno.AsStructHandler[CreateUserRequest](func(req uno.Request, request CreateUserRequest) {
// Handle user creation
user := User{
ID: uuid.New().String(),
Name: request.Name,
Email: request.Email,
}
req.RespondJSON(user)
}))
Interceptors in Uno work similarly to middleware in other frameworks, allowing you to add cross-cutting concerns to your service endpoints. They can modify or enhance the request/response flow, add logging, handle errors, or perform any other operations before or after request processing.
Built-in support for service statistics and Prometheus metrics.
Built-in opentelemetry integration.
Uno includes powerful code generation capabilities that help you quickly scaffold services and generate type-safe clients. The framework can generate service code from YAML definitions.
Define your service in uno.yaml YAML file:
namespace: myapp
name: user-service
package: github.com/myorg/userservice
types:
- name: User
fields:
- name: ID
type: string
- name: Name
type: string
- name: Email
type: string
- name: CreateUserRequest
fields:
- name: Name
type: string
- name: Email
type: string
endpoints:
- name: CreateUser
description: Creates a new user
request: CreateUserRequest
response: User
# Generate full project structure
uno init -f uno.yaml
# Generate only API package
uno apigen -f uno.yaml
The generator creates:
- Type-safe request/response structs
- Client package with strongly-typed methods
- Service interface and implementation stubs
- API documentation (TODO)
Generated code includes:
- Type definitions
- Service interface
- Client implementation
- Request/response handling
- Validation helpers (TODO)
examples README