/ 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  }