boost

package module
v1.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 9 Imported by: 0

README

boost

Enterprise Go services. Built fast.

Boot, config, logs, 58 factories, middleware, health and code generation in one framework. You write the business logic.

release Go MIT

Site · Get started · Examples

go get github.com/xgodev/boost
58 46 107 221
factories libraries plugins releases since 2024

A complete service

A complete service: one route, a service, a repository and two datastores. The generated files and the run are the real output. Full source: docs/site/example/shop.

You write (9 files)

github.com/acme/shop
├── doc.go                                        go:generate
└── internal/
    ├── app/api/rest/
    │   ├── handler/stock/reserver/handler.go     @REST
    │   └── plugins.go                            @Provide
    └── pkg/
        ├── domain/
        │   ├── service/stock/reserver/
        │   │   ├── local/service.go              @Middleware
        │   │   └── service.go                    interface
        │   └── repository/stock/repository.go    interface
        └── datastore/stock/
            ├── memory/datastore.go               @Default
            └── mongodb/
                ├── config.go                     @Config
                └── datastore.go                  @Provide

internal/app/api/rest/handler/stock/reserver/handler.go

// Package reserver serves POST /stock/:sku/reserve.
package reserver

import (
	"net/http"

	"github.com/acme/shop/internal/pkg/domain/service/stock/reserver"
	"github.com/labstack/echo/v4"
)

// Handler reserves one unit of an item.
type Handler struct {
	svc reserver.Service
}

// New provides the handler to the generated rest door.
// @Provide(index=0)
func New(svc reserver.Service) *Handler {
	return &Handler{svc: svc}
}

// Handle reserves one unit of the sku in the path.
// @REST(method=POST, path=/stock/:sku/reserve)
func (h *Handler) Handle(c echo.Context) error {
	if err := h.svc.Reserve(c.Request().Context(), c.Param("sku")); err != nil {
		return err
	}
	return c.NoContent(http.StatusNoContent)
}
internal/app/api/rest/plugins.go
// Package rest holds what the rest server of app api needs besides its
// handlers.
package rest

import (
	boostecho "github.com/xgodev/boost/factory/contrib/labstack/echo/v4"
	"github.com/xgodev/boost/factory/contrib/labstack/echo/v4/plugins/extra/error_handler"
)

// Plugins turns boost errors into HTTP statuses: a Conflict answers 409.
// @Provide(index=0)
func Plugins() []boostecho.Plugin {
	return []boostecho.Plugin{error_handler.Register}
}
internal/pkg/domain/service/stock/reserver/local/service.go
// Package local reserves stock in process, on the stock repository.
package local

import (
	"context"

	"github.com/acme/shop/internal/pkg/domain/repository/stock"
	"github.com/acme/shop/internal/pkg/domain/service/stock/reserver"
)

type service struct {
	repo stock.Repository
}

// New provides the service, wrapped in the log and prometheus middlewares.
// @Provide(index=0)
// @Middleware(log, prometheus)
func New(repo stock.Repository) reserver.Service {
	return &service{repo: repo}
}

func (s *service) Reserve(ctx context.Context, sku string) error {
	return s.repo.Take(ctx, sku)
}
internal/pkg/domain/service/stock/reserver/service.go
// Package reserver reserves one unit of an item.
package reserver

import "context"

// Service reserves stock.
type Service interface {
	Reserve(ctx context.Context, sku string) error
}
internal/pkg/domain/repository/stock/repository.go
// Package stock is the persistence of the units in stock.
package stock

import "context"

// Repository keeps the units in stock of each item.
type Repository interface {
	// Take removes one unit of sku; a sold-out sku is a Conflict.
	Take(ctx context.Context, sku string) error
}
internal/pkg/datastore/stock/memory/datastore.go
// Package memory keeps the stock in memory: the default, no infra needed.
package memory

import (
	"context"
	"sync"

	"github.com/acme/shop/internal/pkg/domain/repository/stock"
	"github.com/xgodev/boost/model/errors"
)

type datastore struct {
	mu    sync.Mutex
	units map[string]int
}

// New provides the stock wired when no other is configured.
// @Provide(index=0)
// @Default
func New() stock.Repository {
	return &datastore{units: map[string]int{"tshirt": 3}}
}

func (d *datastore) Take(_ context.Context, sku string) error {
	d.mu.Lock()
	defer d.mu.Unlock()
	if d.units[sku] == 0 {
		return errors.Conflictf("%s is sold out", sku)
	}
	d.units[sku]--
	return nil
}
internal/pkg/datastore/stock/mongodb/config.go
package mongodb

// Options configures the mongo stock; inject generates its config keys.
// @Config
type Options struct {
	Collection string `default:"stock" desc:"collection of the units in stock"`
}
internal/pkg/datastore/stock/mongodb/datastore.go
// Package mongodb keeps the stock in MongoDB, on boost's mongo factory.
package mongodb

import (
	"context"

	"github.com/acme/shop/internal/pkg/domain/repository/stock"
	mongofact "github.com/xgodev/boost/factory/contrib/go.mongodb.org/mongo-driver/v2"
	"github.com/xgodev/boost/model/errors"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
)

type datastore struct {
	coll *mongo.Collection
}

// New connects through boost's mongo factory (boost.factory.mongo.*).
// @Provide(index=0)
func New(ctx context.Context, o *Options) (stock.Repository, error) {
	conn, err := mongofact.NewConn(ctx)
	if err != nil {
		return nil, err
	}
	return &datastore{coll: conn.Database.Collection(o.Collection)}, nil
}

func (d *datastore) Take(ctx context.Context, sku string) error {
	res, err := d.coll.UpdateOne(ctx,
		bson.M{"_id": sku, "units": bson.M{"$gt": 0}},
		bson.M{"$inc": bson.M{"units": -1}})
	if err != nil {
		return err
	}
	if res.MatchedCount == 0 {
		return errors.Conflictf("%s is sold out", sku)
	}
	return nil
}
doc.go
// Package shop is the example app of the boost site.
package shop

//go:generate go run github.com/xgodev/boost/builder/cmd/builder

Generated (12 files)

cmd/api/main.go                                   main
gen/
├── builder/
│   ├── api/
│   │   ├── modules.go                            app api
│   │   └── rest_module.go                        @REST
│   └── middleware/…/local/new_middleware.go      @Middleware
├── implementation/…/stock/
│   └── repository_implementation.go              @Default
├── internal/
│   ├── app/api/rest/
│   │   ├── handler/stock/reserver/new_module.go
│   │   └── plugins_module.go
│   └── pkg/
│       ├── domain/service/…/local/new_module.go
│       └── datastore/stock/
│           ├── memory/new_module.go
│           └── mongodb/
│               ├── new_module.go
│               └── options_module.go             @Config
└── module.go                                     all modules

cmd/api/main.go

// Code generated by builder; DO NOT EDIT.

// Command api runs app api: the doors builder generates in
// github.com/acme/shop/gen/builder/api.
package main

import (
	app "github.com/acme/shop/gen/builder/api"
	"github.com/xgodev/boost"
	fxfact "github.com/xgodev/boost/factory/contrib/go.uber.org/fx/v1"
)

func main() {
	boost.Start()

	fxfact.NewApp(app.Modules()...).Run()
}
gen/builder/api/modules.go
// Code generated by builder; DO NOT EDIT.

package api

import (
	"go.uber.org/fx"

	mw_local_54c3d838 "github.com/acme/shop/gen/builder/middleware/internal_/pkg/domain/service/stock/reserver/local"
	multiserverfx "github.com/xgodev/boost/fx/modules/extra/multiserver"
)

// Modules returns the doors of app api and the multiserver that runs its servers:
//
//	fxfact.NewApp(api.Modules()...).Run()
func Modules() []fx.Option {
	return []fx.Option{
		RestModule(),
		mw_local_54c3d838.DecorateNew(),
		multiserverfx.Module(),
	}
}
gen/builder/api/rest_module.go
// Code generated by builder; DO NOT EDIT.

package api

import (
	"sync"

	"go.uber.org/fx"

	gen_rest_54b9e997 "github.com/acme/shop/gen/internal/app/api/rest"
	gen_reserver_5a8b66f7 "github.com/acme/shop/gen/internal/app/api/rest/handler/stock/reserver"
	src_reserver_5a8b66f7 "github.com/acme/shop/internal/app/api/rest/handler/stock/reserver"
	boostecho "github.com/xgodev/boost/factory/contrib/labstack/echo/v4"
	echofx "github.com/xgodev/boost/fx/modules/factory/contrib/labstack/echo/v4"
)

var restOnce sync.Once

// RestModule serves the REST routes of server rest on echo.
// It returns an empty option after the first call.
func RestModule() fx.Option {
	options := fx.Options()

	restOnce.Do(func() {
		options = fx.Module("api.rest",
			echofx.Module(),
			gen_reserver_5a8b66f7.NewModule(),
			gen_rest_54b9e997.PluginsModule(),
			fx.Invoke(func(srv *boostecho.Server, h0 *src_reserver_5a8b66f7.Handler) {
				srv.Add("POST", "/stock/:sku/reserve", h0.Handle)
			}),
		)
	})

	return options
}
gen/builder/middleware/internal_/pkg/domain/service/stock/reserver/local/new_middleware.go
// Code generated by builder; DO NOT EDIT.

package local

import (
	"go.uber.org/fx"

	context "context"
	src_reserver_399f2048 "github.com/acme/shop/internal/pkg/domain/service/stock/reserver"
	middleware "github.com/xgodev/boost/extra/middleware"
	fmiddleware "github.com/xgodev/boost/factory/local/extra/middleware"
	prometheusmw "github.com/xgodev/boost/factory/local/extra/middleware/plugins/contrib/prometheus/client_golang/v1"
	logmw "github.com/xgodev/boost/factory/local/extra/middleware/plugins/local/wrapper/log"
	contextfx "github.com/xgodev/boost/fx/modules/core/context"
)

// DecorateNew decorates the reserver.Service that local.New provides:
// every consumer in the app receives a newDecorator, which runs the middlewares
// log, prometheus around each method; config can disable each one.
func DecorateNew() fx.Option {
	return fx.Options(
		contextfx.Module(),
		fx.Decorate(decorateNew),
	)
}

// decorateNew builds the wrappers of every method of reserver.Service once.
func decorateNew(ctx context.Context, next src_reserver_399f2048.Service) (src_reserver_399f2048.Service, error) {
	d := &newDecorator{next: next}
	var err error

	d.reserveWrapper, err = fmiddleware.NewErrorWrapperWithOptions(ctx, &fmiddleware.Options{Name: "reserver.service.reserve"},
		logmw.NewError,
		prometheusmw.NewError,
	)
	if err != nil {
		return nil, err
	}

	return d, nil
}

// newDecorator implements reserver.Service: each method runs next's in its wrapper.
type newDecorator struct {
	next           src_reserver_399f2048.Service
	reserveWrapper *middleware.ErrorWrapper
}

// Reserve runs next.Reserve in the middlewares of reserver.service.reserve.
func (d *newDecorator) Reserve(ctx context.Context, a1 string) error {
	return d.reserveWrapper.Exec(ctx, "reserver.service.reserve",
		func(ctx context.Context) error {
			return d.next.Reserve(ctx, a1)
		},
		func(_ context.Context, err error) error {
			return err
		},
	)
}
gen/implementation/internal_/pkg/domain/repository/stock/repository_implementation.go
// Code generated by inject; DO NOT EDIT.

package stock

import (
	"sync"

	"github.com/xgodev/boost/model/errors"
	"github.com/xgodev/boost/wrapper/config"
	"go.uber.org/fx"

	gen_memory_6a1a5ba1 "github.com/acme/shop/gen/internal/pkg/datastore/stock/memory"
	gen_mongodb_1bacb721 "github.com/acme/shop/gen/internal/pkg/datastore/stock/mongodb"
)

// repositoryImplementationKey chooses the implementation of github.com/acme/shop/internal/pkg/domain/repository/stock.Repository.
const repositoryImplementationKey = "internal.pkg.domain.repository.stock.implementation"

func init() {
	config.Add(repositoryImplementationKey, "memory", "implementation of github.com/acme/shop/internal/pkg/domain/repository/stock.Repository: memory, mongodb")
}

// RepositoryImplementation returns the name of the implementation of
// github.com/acme/shop/internal/pkg/domain/repository/stock.Repository that RepositoryImplementationModule wires.
func RepositoryImplementation() string {
	return config.String(repositoryImplementationKey)
}

var repositoryImplementationOnce sync.Once

// RepositoryImplementationModule wires the implementation of github.com/acme/shop/internal/pkg/domain/repository/stock.Repository
// named by internal.pkg.domain.repository.stock.implementation (memory, mongodb; default memory) and only that one.
// An unknown name fails the boot. It returns an empty option after the first
// call, so every consumer can include it.
func RepositoryImplementationModule() fx.Option {
	options := fx.Options()

	repositoryImplementationOnce.Do(func() {
		switch name := RepositoryImplementation(); name {
		case "memory":
			options = gen_memory_6a1a5ba1.NewModule()
		case "mongodb":
			options = gen_mongodb_1bacb721.NewModule()
		default:
			options = fx.Error(errors.NotValidf("%s: unknown implementation %q; valid: %s", repositoryImplementationKey, name, "memory, mongodb"))
		}
	})

	return options
}
gen/internal/pkg/datastore/stock/mongodb/options_module.go
// Code generated by inject; DO NOT EDIT.

package mongodb

import (
	"sync"

	"github.com/xgodev/boost/wrapper/config"
	"go.uber.org/fx"

	src_mongodb_1bacb721 "github.com/acme/shop/internal/pkg/datastore/stock/mongodb"
)

// optionsRoot is the config key holding github.com/acme/shop/internal/pkg/datastore/stock/mongodb.Options.
const optionsRoot = "internal.pkg.datastore.stock.mongodb"

func init() {
	// env INTERNAL_PKG_DATASTORE_STOCK_MONGODB_COLLECTION
	config.Add(optionsRoot+".collection", "stock", "collection of the units in stock")
}

var optionsOnce sync.Once

// OptionsModule provides the Options of github.com/acme/shop/internal/pkg/datastore/stock/mongodb,
// filled from the config keys under internal.pkg.datastore.stock.mongodb.
// It returns an empty option after the first call, so every consumer can
// include it.
func OptionsModule() fx.Option {
	options := fx.Options()

	optionsOnce.Do(func() {
		options = fx.Module("github.com/acme/shop/internal/pkg/datastore/stock/mongodb.Options",
			fx.Provide(func() (*src_mongodb_1bacb721.Options, error) {
				return config.NewOptionsWithPath[src_mongodb_1bacb721.Options](optionsRoot)
			}),
		)
	})

	return options
}

The other generated files are in docs/site/example/shop/gen.

Run

$ go generate ./...
5:35PM INF scanning ~/shop (module github.com/acme/shop)
5:35PM INF generated 6 inject modules and 1 apps in ~/shop/gen, mains in ~/shop/cmd
$ go run ./cmd/api &
5:36PM INF starting Echo Server. https://echo.labstack.com/
# memory is the @Default datastore: 3 t-shirts in stock
$ for i in 1 2 3 4; do curl -s -w ' %{http_code}\n' -X POST localhost:8080/stock/tshirt/reserve; done
 204
 204
 204
{"httpStatusCode":409,"errorCode":"409","message":"tshirt is sold out"}
 409
# same binary on MongoDB, through boost's mongo factory:
# INTERNAL_PKG_DOMAIN_REPOSITORY_STOCK_IMPLEMENTATION=mongodb

One boot. Everything ready after it.

boost.Start() runs first. When it returns, config is loaded and the logger is set, so every factory reads its own keys and logs the same way.

01 boost.Start() Reads flags, env vars and config files.
02 config Every key declared once, with a default and a description.
03 log zap, zerolog or logrus behind one wrapper.
04 factory One constructor per component, plugins applied.
05 fx Generated modules wire the dependency graph.
06 serve REST, gRPC, MCP or an event function.

One key, three ways to set it

Keys live under boost.factory.<component>.* and reach the app from wherever you deploy.

key boost.factory.zap.console.level
env BOOST_FACTORY_ZAP_CONSOLE_LEVEL=DEBUG
flag --boost.factory.zap.console.level=DEBUG
// cmd/api/main.go, written by go generate
func main() {
	boost.Start()
	fxfact.NewApp(app.Modules()...).Run()
}

bootstrap

Every piece has one job.

Factories build, wrappers abstract, generators remove the wiring. Use one package or all of them.

Factories

factory/contrib/labstack/echo/v4 · docs

One constructor per component. You never instantiate the SDK by hand: the factory reads its config keys, applies the plugins you list and returns the ready client.

srv, _ := echo.NewServer(ctx,
	cors.Register,
	requestid.Register,
	gzip.Register,
	log.Register,
	health.Register,
)
srv.GET("/stock/:sku", Get)
srv.Serve(ctx)

58 factories · 46 upstream libraries · 107 plugins

Plugins

…/echo/v4/plugins

Behaviour you opt into per factory, applied in the order you list it.

cors requestid gzip log health recover bodylimit prometheus otel datadog swaggo semaphore

Wrappers

wrapper/{log,config,cache,publisher} · docs

Swap zap for zerolog by changing one line in main. App code only ever calls the wrapper.

log.FromContext(ctx).
	Infof("reserved %s", sku)

Middleware

extra/middleware · docs

Wraps any call in log, cache, hystrix, datadog, prometheus or fallback. With @Middleware the decorator is generated and the method body stays clean.

log
└── prometheus
    └── hystrix
        └── Service.Reserve()

@Middleware(log, prometheus, hystrix) · first is outermost

Inject

inject · docs

@Provide, @Inject and @Invoke become one fx module per function and a root Module().

@Default     memory.New | mongodb.New   stock.Repository
    ↓
@Middleware  local.New(repo)            reserver.Service
    ↓
@Provide     reserver.New(svc)          *Handler
    ↓
@REST        Handler.Handle             POST /stock/:sku/reserve
  • cycles and missing providers fail at go generate, not in production
  • two providers of the same value are rejected

Annotation

annotation · docs

Reads // @Name(key=value) from doc comments into typed structs. Every generator here is built on it.

var r struct {
	Path string `attr:"path"`
}
ann.Decode(&r)

Builder

builder · docs

An annotation says which door serves the handler. The builder writes the door, the app modules and main.

@REST echo route
@GRPC gRPC service
@Function azure functions · cloudevents · kafka · kafka-go · lambda · nats · pubsub
@MCP MCP tool
@Middleware generated decorator
@Default implementation picked by config

Functions

bootstrap/function · docs

One event handler, six transports. Change the adapter in config; the handler stays the same.

func(ctx, in cloudevents.Event)
	(*cloudevents.Event, error)

MCP

factory/contrib/modelcontextprotocol/go-sdk/v1/{server,client}

Your use cases become tools that agents call over MCP, and your service calls other MCP servers. Server and client are factories like the rest: config keys, plugins, and the server runs beside echo and gRPC. Mark a handler with @MCP and the builder registers it as a tool.

server · HTTP server · STDIO client · HTTP client · COMMAND log otel

srv, _ := server.NewServer(ctx, mcplog.Register, otel.Register)
mcp.AddTool(srv.Instance(), &mcp.Tool{
	Name:        "reserve",
	Description: "holds items for an order",
}, reserve)
srv.Serve(ctx)

From annotation to binary in two commands.

You write handlers, services and annotations. Everything that repeats between services is generated, checked and rewritten on every run.

  1. Annotate. Mark constructors with @Provide, handlers with a door, services with @Middleware, the default implementation with @Default, options with @Config.

  2. Generate. Inject and builder run in one pass. A broken graph stops here and leaves your output untouched.

    go generate ./...
    
  3. Run. Each app gets its own main, with the servers and plugins it declared.

    go run ./cmd/api
    

Generated output, rewritten on every run:

cmd/api/main.go                // boost.Start(), then app api
gen/
├── builder/
│   ├── api/
│   │   ├── modules.go         // the doors of app api
│   │   └── rest_module.go     // @REST POST /stock/:sku/reserve
│   └── middleware/…/local/
│       └── new_middleware.go  // @Middleware(log, prometheus)
├── implementation/…/stock/
│   └── repository_implementation.go
│                              // @Default: memory | mongodb
├── internal/
│   ├── app/…                  // one module per @Provide,
│   └── pkg/…                  // @Config: same tree as yours
└── module.go                  // every inject module

Upgrade boost. Keep your code.

A minor release never asks you to rewrite a service. That is a rule of the project, enforced on every pull request.

Public API is a contract

A component's public API does not break without a major version bump and a written reason. Any observable change ships with a test first.

SDK majors live side by side

Factory paths carry the upstream major. Moving to a new SDK is an import you choose, not a forced migration.

factory/contrib/go.mongodb.org/mongo-driver/v1   // keeps working
factory/contrib/go.mongodb.org/mongo-driver/v2   // new SDK major

A gate that only moves forward

Every PR is compared to develop: format, lint, build and tests can stay the same or get better, never worse.

 module github.com/acme/shop

 require (
-	github.com/xgodev/boost v1.1.1
+	github.com/xgodev/boost v1.6.1
 )
$ go build ./... && go test ./...
ok  github.com/acme/shop/...

1 line changed in go.mod, 0 lines changed in your code.

Releases: 2024-07 → v1.1.0 → v1.1.1 → v1.6.1 (all releases).

There's a factory for that.

58 factories over the 46 libraries your services already run on. Each one arrives configured, with plugins for traces, metrics and health checks, so your team writes the business logic, not the plumbing.

Web, RPC & MCP

Library Factory wraps
Echo echo/v4 · v5
chi chi/v5
Fiber fiber/v2
gRPC server · client grpc/v1
MCP server · client go-sdk/v1
HTTP/2 server x/net/v0
GraphQL graphql-go/v0
Resty resty/v2
fasthttp client fasthttp/v1
drpc server · client drpc/v1

Messaging

Library Factory wraps
Kafka (Confluent) confluent-kafka-go/v2
Kafka (segmentio) kafka-go/v0
NATS nats.go/v1
Google Pub/Sub pubsub/v1 · v2
Go CDK Pub/Sub gocloud.dev/v0
CloudEvents sdk-go/v2
Goka goka/v1
SQS · SNS · Kinesis aws-sdk-go-v2

Data

Library Factory wraps
MongoDB mongo-driver/v1 · v2
PostgreSQL pgx/v5
Oracle godror/v0
Cassandra gocql/v1 · v2
Elasticsearch go-elasticsearch/v8 · v9
BigQuery · Bigtable · Firestore · API client cloud.google.com
FTP ftp/v0
Azure Blob Storage azure-sdk-for-go/v1

Cache

Library Factory wraps
Redis go-redis/v9
BigCache bigcache/v3
FreeCache freecache/v1
BuntDB buntdb/v1
memdb memdb/v1

Observability

Library Factory wraps
OpenTelemetry otel/v1
Datadog dd-trace-go/v1
Prometheus client_golang/v1
Hystrix hystrix-go/v0

Logging & platform

Library Factory wraps
zap · zerolog · logrus wrapper/log
fx fx/v1
Cobra cobra/v1
Kubernetes client-go/v0
Vault vaultgo/v0
ants worker pool ants/v2

Why a factory, not just the SDK

Any SDK connects in five lines. Running it in a company takes the rest: config per environment, auth, checks, logs, metrics, traces. That part is the same in every service, so boost writes it once.

  • Configured, not coded. Every option is a config key with a default, read from file or environment: boost.factory.mongo.uri is BOOST_FACTORY_MONGO_URI. One binary for every environment.
  • The plumbing comes built. Defaults, auth, connect and ping, structured logs through wrapper/log. What a platform team rewrites for every SDK in every service is already there.
  • 78 plugins to plug in. OpenTelemetry, Prometheus, Datadog, health checks, retry, request id, CORS, gzip. Pass the plugin to the factory; switch it off with a key.

By hand: MongoDB, in every service

  • Read URI, user and password from the environment, with defaults
  • Build the client options and the authentication
  • Connect and ping before taking traffic
  • Trace every command with OpenTelemetry
  • Count commands and errors in Prometheus
  • Register a health check
  • Log commands when you need to debug
  • Then again for Kafka, Redis, gRPC, the HTTP client…

With boost: factory/contrib/go.mongodb.org/mongo-driver/v2

conn, err := mongo.NewConn(ctx,
	mongootel.Register,   // traces
	mongoprom.Register,   // metrics
	mongohealth.Register, // health check
)
$ export BOOST_FACTORY_MONGO_URI=mongodb://db:27017/shop
$ export BOOST_FACTORY_MONGO_AUTH_USERNAME=shop
$ export BOOST_FACTORY_MONGO_PLUGINS_PROMETHEUS_ENABLED=false

Same shape for every factory: New…(ctx, plugins...) and keys under boost.factory.<name>.

Coding agents that follow the rules.

The claude-plugin@xgodev plugin teaches Claude Code boost's Iron Laws and the project layout, and runs the comparative quality gate before every push.

/plugin marketplace add xgodev/claude-plugin
/plugin install claude-plugin@xgodev
  1. boost.Start() first. Config and log exist only after it.
  2. Log only through wrapper/log. log.FromContext(ctx), never a third-party logger in app code.
  3. Config only through wrapper/config. No os.Getenv; keys under boost.factory.<x>.*.
  4. One factory per component. Never instantiate the upstream SDK directly.
  5. Backward compatible. Public API breaks only with a major bump and a reason.

Start with one line.

go get github.com/xgodev/boost

See the examples · Star on GitHub


boost · xgodev · MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplicationName

func ApplicationName() string

func Start

func Start()

Types

This section is empty.

Directories

Path Synopsis
examples/decode command
examples/func command
examples/method command
examples/simple command
Package builder generates the doors of an application (REST routes on echo, gRPC services, MCP tools and event functions) from @REST, @GRPC, @MCP and @Function annotations, on top of the fx modules generated by inject.
Package builder generates the doors of an application (REST routes on echo, gRPC services, MCP tools and event functions) from @REST, @GRPC, @MCP and @Function annotations, on top of the fx modules generated by inject.
cmd/builder command
Command builder generates the inject modules, the door modules and the main of every app from the annotations of an application, in one pass.
Command builder generates the inject modules, the door modules and the main of every app from the annotations of an application, in one pass.
examples/simple
Package simple is an application whose doors come from builder annotations: app api serves REST routes on two echo servers (rest and admin), a gRPC health service and the check_stock MCP tool; app worker records the orders of order.created events.
Package simple is an application whose doors come from builder annotations: app api serves REST routes on two echo servers (rest and admin), a gRPC health service and the check_stock MCP tool; app worker records the orders of order.created events.
examples/simple/cmd/api command
Command api runs app api: the doors builder generates in github.com/xgodev/boost/builder/examples/simple/gen/builder/api.
Command api runs app api: the doors builder generates in github.com/xgodev/boost/builder/examples/simple/gen/builder/api.
examples/simple/cmd/worker command
Command worker runs app worker: the doors builder generates in github.com/xgodev/boost/builder/examples/simple/gen/builder/worker.
Command worker runs app worker: the doors builder generates in github.com/xgodev/boost/builder/examples/simple/gen/builder/worker.
examples/simple/createorder
Package createorder serves the order routes of app api.
Package createorder serves the order routes of app api.
examples/simple/healthcheck
Package healthcheck serves grpc.health.v1.Health on the grpc server of app api.
Package healthcheck serves grpc.health.v1.Health on the grpc server of app api.
examples/simple/order
Package order keeps the orders of the example in memory.
Package order keeps the orders of the example in memory.
examples/simple/ordercreated
Package ordercreated records the orders of order.created events in app worker.
Package ordercreated records the orders of order.created events in app worker.
examples/simple/probe
Package probe answers the liveness probe on the admin server of app api, apart from the public routes.
Package probe answers the liveness probe on the admin server of app api, apart from the public routes.
examples/simple/stock
Package stock tells whether an item can be ordered.
Package stock tells whether an item can be ordered.
examples/simple/stock/memory
Package memory keeps the stock in memory.
Package memory keeps the stock in memory.
examples/simple/stock/remote
Package remote asks a warehouse over HTTP for the stock.
Package remote asks a warehouse over HTTP for the stock.
examples/simple/stock/unlimited
Package unlimited is a stock without limits.
Package unlimited is a stock without limits.
examples/simple/stocktool
Package stocktool serves the stock tools of app api over MCP.
Package stocktool serves the stock tools of app api over MCP.
extra
Package factory holds the contract shared by every factory under it.
Package factory holds the contract shared by every factory under it.
contrib/apache/cassandra-gocql-driver/v2
Package gocql builds Cassandra sessions with the gocql v2 driver (github.com/apache/cassandra-gocql-driver/v2), configured under boost.factory.gocql.* -- the keys of the gocql v1 factory (factory/contrib/gocql/gocql/v1), so moving to v2 only changes the import.
Package gocql builds Cassandra sessions with the gocql v2 driver (github.com/apache/cassandra-gocql-driver/v2), configured under boost.factory.gocql.* -- the keys of the gocql v1 factory (factory/contrib/gocql/gocql/v1), so moving to v2 only changes the import.
contrib/apache/cassandra-gocql-driver/v2/plugins/local/extra/health
Package health registers a gocql v2 session as a checker of github.com/xgodev/boost/extra/health, configured under boost.factory.gocql.plugins.health.*.
Package health registers a gocql v2 session as a checker of github.com/xgodev/boost/extra/health, configured under boost.factory.gocql.plugins.health.*.
contrib/elastic/go-elasticsearch/v9
Package elasticsearch is boost's factory for the go-elasticsearch v9 client: options under boost.factory.elasticsearch, a ping on creation and plugins run on the built client.
Package elasticsearch is boost's factory for the go-elasticsearch v9 client: options under boost.factory.elasticsearch, a ping on creation and plugins run on the built client.
contrib/elastic/go-elasticsearch/v9/plugins/local/extra/health
Package health registers a go-elasticsearch v9 client in boost's extra/health: the checker pings the cluster, and an error status fails it.
Package health registers a go-elasticsearch v9 client in boost's extra/health: the checker pings the cluster, and an error status fails it.
contrib/go-resty/resty/v2/plugins/contrib/dubonzi/otelresty/v1
This package implements integration between the go-resty (https://github.com/go-resty/resty) library and OpenTelemetry.
This package implements integration between the go-resty (https://github.com/go-resty/resty) library and OpenTelemetry.
contrib/go.mongodb.org/mongo-driver/v1/plugins/contrib/go.opentelemetry.io/contrib/v0
This package implements integration between the official go mongodb driver (https://github.com/mongodb/mongo-go-driver) and OpenTelemetry.
This package implements integration between the official go mongodb driver (https://github.com/mongodb/mongo-go-driver) and OpenTelemetry.
contrib/go.mongodb.org/mongo-driver/v2/plugins/contrib/go.opentelemetry.io/contrib/v0
This package implements integration between the official go mongodb driver (https://github.com/mongodb/mongo-go-driver) and OpenTelemetry.
This package implements integration between the official go mongodb driver (https://github.com/mongodb/mongo-go-driver) and OpenTelemetry.
contrib/labstack/echo/v4/plugins/contrib/go.opentelemetry.io/contrib/v0
This package implements integration between echo (https://github.com/labstack/echo) and OpenTelemetry.
This package implements integration between echo (https://github.com/labstack/echo) and OpenTelemetry.
contrib/labstack/echo/v5/plugins/contrib/swaggo/echo-swagger/v2
Package swagger serves the Swagger UI and the swag docs on an echo v5 server, through github.com/swaggo/echo-swagger/v2.
Package swagger serves the Swagger UI and the swag docs on an echo v5 server, through github.com/swaggo/echo-swagger/v2.
contrib/modelcontextprotocol/go-sdk/v1/client/plugins/contrib/go.opentelemetry.io/otel/v1
Package otel opens an OpenTelemetry span for every MCP call the client sends, propagating the trace to the server in _meta.
Package otel opens an OpenTelemetry span for every MCP call the client sends, propagating the trace to the server in _meta.
contrib/modelcontextprotocol/go-sdk/v1/client/plugins/local/wrapper/log
Package log logs every MCP call the client sends through wrapper/log: method, tool, duration and error.
Package log logs every MCP call the client sends through wrapper/log: method, tool, duration and error.
contrib/modelcontextprotocol/go-sdk/v1/internal/buildinfo
Package buildinfo reads the application version Go stamps into the binary.
Package buildinfo reads the application version Go stamps into the binary.
contrib/modelcontextprotocol/go-sdk/v1/internal/middleware
Package middleware holds the go-sdk middlewares the server and client plugins install: one call in, one log line or span out.
Package middleware holds the go-sdk middlewares the server and client plugins install: one call in, one log line or span out.
contrib/modelcontextprotocol/go-sdk/v1/server/plugins/contrib/go.opentelemetry.io/otel/v1
Package otel opens an OpenTelemetry span for every MCP call the server receives, continuing the trace the client sent in _meta.
Package otel opens an OpenTelemetry span for every MCP call the server receives, continuing the trace the client sent in _meta.
contrib/modelcontextprotocol/go-sdk/v1/server/plugins/local/wrapper/log
Package log logs every MCP call the server receives through wrapper/log: method, tool, duration and error.
Package log logs every MCP call the server receives through wrapper/log: method, tool, duration and error.
fx
modules/bootstrap/function/adapter/contrib/cloud.google.com/pubsub
Package pubsub declares, once, the config the Pub/Sub v1 and v2 function adapter fx modules share: whether the adapter is on and which version it is.
Package pubsub declares, once, the config the Pub/Sub v1 and v2 function adapter fx modules share: whether the adapter is on and which version it is.
modules/factory/contrib/cloud.google.com/pubsub
Package pubsub holds what the Pub/Sub v1 and v2 fx modules share: the version values and the factory's version key, declared once.
Package pubsub holds what the Pub/Sub v1 and v2 fx modules share: the version values and the factory's version key, declared once.
modules/factory/contrib/elastic/go-elasticsearch/v9
Package elastic provides the fx modules of boost's go-elasticsearch v9 factory.
Package elastic provides the fx modules of boost's go-elasticsearch v9 factory.
modules/wrapper/publisher/driver/contrib/cloud.google.com/pubsub
Package pubsub declares, once, the config the Pub/Sub v1 and v2 publisher driver fx modules share: whether the driver is on and which version it is.
Package pubsub declares, once, the config the Pub/Sub v1 and v2 publisher driver fx modules share: whether the driver is on and which version it is.
cmd/inject command
Command inject generates fx modules from @Provide, @Inject and @Invoke annotations.
Command inject generates fx modules from @Provide, @Inject and @Invoke annotations.
examples/clients command
Command clients wires a NATS connection, a Pub/Sub client, gocql sessions of both drivers and a Bigtable client that inject builds from @Inject, and stops them with the app.
Command clients wires a NATS connection, a Pub/Sub client, gocql sessions of both drivers and a Bigtable client that inject builds from @Inject, and stops them with the app.
examples/clients/catalog
Package catalog stores the prices of the catalog in Bigtable through the "catalog" client.
Package catalog stores the prices of the catalog in Bigtable through the "catalog" client.
examples/clients/events
Package events publishes events over the "events" NATS connection.
Package events publishes events over the "events" NATS connection.
examples/clients/ledger
Package ledger reads the Cassandra/ScyllaDB cluster through the "ledger" session of the Apache driver (github.com/apache/cassandra-gocql-driver/v2).
Package ledger reads the Cassandra/ScyllaDB cluster through the "ledger" session of the Apache driver (github.com/apache/cassandra-gocql-driver/v2).
examples/clients/orders
Package orders manages the Pub/Sub topics of orders through the "orders" client.
Package orders manages the Pub/Sub topics of orders through the "orders" client.
examples/clients/store
Package store reads the Cassandra/ScyllaDB cluster through the "store" session.
Package store reads the Cassandra/ScyllaDB cluster through the "store" session.
examples/publisher command
Command publisher announces a created order through the publisher inject builds, on the driver boost.wrapper.publisher.driver.name chooses (noop by default).
Command publisher announces a created order through the publisher inject builds, on the driver boost.wrapper.publisher.driver.name chooses (noop by default).
examples/publisher/domain/model/entity
Package entity holds the entities of the example.
Package entity holds the entities of the example.
examples/publisher/domain/publisher/ordercreated
Package ordercreated announces that an order was created.
Package ordercreated announces that an order was created.
examples/publisher/publisher/ordercreated/boost
Package boost implements ordercreated.Publisher on boost's wrapper/publisher, whose driver config chooses.
Package boost implements ordercreated.Publisher on boost's wrapper/publisher, whose driver config chooses.
examples/simple command
Command simple wires an fx application from inject annotations.
Command simple wires an fx application from inject annotations.
examples/simple/app
Package app consumes the values provided by the other packages.
Package app consumes the values provided by the other packages.
examples/simple/greeting
Package greeting provides the greeters used by the example.
Package greeting provides the greeters used by the example.
examples/simple/names
Package names contributes values to the "names" group.
Package names contributes values to the "names" group.
internal
cassandratest
Package cassandratest gives the tests of the gocql v2 factory, its plugins and its fx module a Cassandra to talk to.
Package cassandratest gives the tests of the gocql v2 factory, its plugins and its fx module a Cassandra to talk to.
configtest
Package configtest sets boost config values from tests.
Package configtest sets boost config values from tests.
model
errors
Package errors provides an easy way to annotate errors without losing the original error context.
Package errors provides an easy way to annotate errors without losing the original error context.
utils
wrapper
cache/codec/contrib/shamaton/msgpack/v3
Package msgpack is a wrapper/cache codec on github.com/shamaton/msgpack/v3.
Package msgpack is a wrapper/cache codec on github.com/shamaton/msgpack/v3.
config
Package config provides a wrapper around koanf.
Package config provides a wrapper around koanf.
config/contrib/knadh/koanf/v2
Package koanf is the boost config driver on koanf v2.
Package koanf is the boost config driver on koanf v2.
log
Package log provides a generic interface around loggers.
Package log provides a generic interface around loggers.
publisher/driver/contrib/aws/kinesis/v1
Package kinesis is a publisher driver that puts each event in the Kinesis stream named by the event subject.
Package kinesis is a publisher driver that puts each event in the Kinesis stream named by the event subject.
publisher/driver/contrib/aws/sns/v1
Package sns is a publisher driver that sends each event to the SNS topic whose ARN is the event subject.
Package sns is a publisher driver that sends each event to the SNS topic whose ARN is the event subject.
publisher/driver/contrib/aws/sqs/v1
Package sqs is a publisher driver that sends each event to the SQS queue named by the event subject.
Package sqs is a publisher driver that sends each event to the SQS queue named by the event subject.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL