/ middleware.go
middleware.go
1 package dispatch2 2 3 import ( 4 "context" 5 "log" 6 ) 7 8 type Middleware[Config any] interface { 9 Wrap(ExecuterFunc[Config]) ExecuterFunc[Config] 10 } 11 12 type MiddlewareFunc[Config any] func(next ExecuterFunc[Config]) ExecuterFunc[Config] 13 14 func (m MiddlewareFunc[Config]) Wrap(next ExecuterFunc[Config]) ExecuterFunc[Config] { 15 return m(next) 16 } 17 18 func invertMiddleware[Config any](m MiddlewareFunc[Config]) MiddlewareFunc[Config] { 19 return func(next ExecuterFunc[Config]) ExecuterFunc[Config] { 20 return func(ctx context.Context, cfg *Config, args []string) error { 21 // First execute the core/next middleware 22 if err := next(ctx, cfg, args); err != nil { 23 return err 24 } 25 // Then execute the original middleware logic with a no-op next 26 return m(func(ctx context.Context, cfg *Config, args []string) error { 27 return nil 28 })(ctx, cfg, args) 29 } 30 } 31 } 32 33 // Example middlewares 34 35 func MiddlewareHelloWorld[Config any]() MiddlewareFunc[Config] { 36 return func(next ExecuterFunc[Config]) ExecuterFunc[Config] { 37 return func(ctx context.Context, cfg *Config, args []string) error { 38 // Note: inversion is applied on After middlewares, so all middlewares can 39 // follow this same boilerplate. 40 log.Println("[MiddlewareHelloWorld] Hello, world!") 41 return next(ctx, cfg, args) 42 } 43 } 44 } 45 46 func MiddlewarePrinter[Config any](message string) MiddlewareFunc[Config] { 47 return func(next ExecuterFunc[Config]) ExecuterFunc[Config] { 48 return func(ctx context.Context, cfg *Config, args []string) error { 49 log.Printf("[MiddlewarePrinter] %s", message) 50 return next(ctx, cfg, args) 51 } 52 } 53 }