mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-08 08:32:16 +01:00
125 lines
3.2 KiB
Go
125 lines
3.2 KiB
Go
package gotenberg
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// Context is a struct that helps to initialize modules. When provisioning, a
|
|
// module may use the context to get other modules that it needs internally.
|
|
type Context struct {
|
|
flags ParsedFlags
|
|
descriptors []ModuleDescriptor
|
|
moduleInstances map[string]any
|
|
}
|
|
|
|
// NewContext creates a [Context].
|
|
// In a module, prefer the [Provisioner] interface to get a [Context].
|
|
func NewContext(
|
|
flags ParsedFlags,
|
|
descriptors []ModuleDescriptor,
|
|
) *Context {
|
|
return &Context{
|
|
flags: flags,
|
|
descriptors: descriptors,
|
|
moduleInstances: make(map[string]any),
|
|
}
|
|
}
|
|
|
|
// ParsedFlags returns the parsed flags.
|
|
//
|
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
|
// flags := ctx.ParsedFlags()
|
|
// m.foo = flags.RequiredString("foo")
|
|
// }
|
|
func (ctx *Context) ParsedFlags() ParsedFlags {
|
|
return ctx.flags
|
|
}
|
|
|
|
// Module returns a module which satisfies the requested interface.
|
|
//
|
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
|
// mod, _ := ctx.Module(new(ModuleInterface))
|
|
// real := mod.(ModuleInterface)
|
|
// }
|
|
//
|
|
// If the module has not yet been initialized, this method
|
|
// initializes it. Otherwise, returns the already initialized instance.
|
|
func (ctx *Context) Module(kind any) (any, error) {
|
|
mods, err := ctx.Modules(kind)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("get module: %w", err)
|
|
}
|
|
|
|
if len(mods) != 1 {
|
|
return nil, fmt.Errorf("expected to have one and only one %s module", kind)
|
|
}
|
|
|
|
return mods[0], nil
|
|
}
|
|
|
|
// Modules return the list of modules which satisfies the requested interface.
|
|
//
|
|
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
|
|
// mods, _ := ctx.Modules(new(ModuleInterface))
|
|
// for _, mod := range mods {
|
|
// real := mod.(ModuleInterface)
|
|
// // ...
|
|
// }
|
|
// }
|
|
//
|
|
// If one or more modules have not yet been initialized, this method
|
|
// initializes them. Otherwise, returns the already initialized instances.
|
|
func (ctx *Context) Modules(kind any) ([]any, error) {
|
|
realKind := reflect.TypeOf(kind).Elem()
|
|
|
|
var mods []any
|
|
|
|
for _, desc := range ctx.descriptors {
|
|
newInstance := desc.New()
|
|
|
|
if ok := reflect.TypeOf(newInstance).Implements(realKind); ok {
|
|
// The module implements the requested interface.
|
|
// We check if it has already been initialized.
|
|
instance, ok := ctx.moduleInstances[desc.ID]
|
|
|
|
if ok {
|
|
mods = append(mods, instance)
|
|
} else {
|
|
err := ctx.loadModule(desc.ID, newInstance)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mods = append(mods, newInstance)
|
|
}
|
|
}
|
|
}
|
|
|
|
return mods, nil
|
|
}
|
|
|
|
// loadModule calls the Provision and/or Validate methods of the requested
|
|
// module if it satisfies the [Provisioner] and/or [Validator] interfaces.
|
|
func (ctx *Context) loadModule(id string, instance any) error {
|
|
if prov, ok := instance.(Provisioner); ok {
|
|
// The instance can be provisioned.
|
|
err := prov.Provision(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("provision module %s: %w", id, err)
|
|
}
|
|
}
|
|
|
|
if validator, ok := instance.(Validator); ok {
|
|
// The instance can be validated.
|
|
err := validator.Validate()
|
|
if err != nil {
|
|
return fmt.Errorf("validate module %s: %w", id, err)
|
|
}
|
|
}
|
|
|
|
ctx.moduleInstances[id] = instance
|
|
|
|
return nil
|
|
}
|