feat(01-01): boot hello app and dispatch greeter:hello

- Add party plugin registry with Register-before-Boot activation
- Add backpack, compass, bonfire, and pact capability interfaces
- Add examples/hello with two compiled plugin modules
This commit is contained in:
Jakub Zych
2026-09-16 12:57:18 +02:00
parent 552cadbdf9
commit 96a8d38be2
26 changed files with 982 additions and 0 deletions

110
bonfire/command.go Normal file
View File

@@ -0,0 +1,110 @@
package bonfire
import (
"context"
"fmt"
"io"
"github.com/spf13/cobra"
)
// Command is a console command value collected from plugins or the tool.
type Command struct {
Name string
Description string
Flags []Flag
Args []Arg
Run func(ctx context.Context, in Input, out Output) error
}
// Flag describes a string flag passed to a command.
type Flag struct {
Name string
Shorthand string
Description string
Default string
}
// Arg describes a positional argument.
type Arg struct {
Name string
Description string
Required bool
}
// Input is the parsed argument and flag view handed to Command.Run.
type Input interface {
Args() []string
Argument(name string) (string, bool)
Flag(name string) (string, bool)
}
// Output is an injected writer used by commands instead of package-level stdout.
type Output interface {
io.Writer
Println(a ...any)
Printf(format string, a ...any)
}
type cobraInput struct {
cmd *cobra.Command
spec Command
args []string
}
func (in cobraInput) Args() []string { return in.args }
func (in cobraInput) Argument(name string) (string, bool) {
for i, arg := range in.spec.Args {
if arg.Name == name {
if i < len(in.args) {
return in.args[i], true
}
return "", false
}
}
return "", false
}
func (in cobraInput) Flag(name string) (string, bool) {
if in.cmd == nil || in.cmd.Flags() == nil {
return "", false
}
if !in.cmd.Flags().Changed(name) {
val, err := in.cmd.Flags().GetString(name)
if err != nil || val == "" {
return "", false
}
return val, true
}
val, err := in.cmd.Flags().GetString(name)
if err != nil {
return "", false
}
return val, true
}
type writerOutput struct {
w io.Writer
}
func (o writerOutput) Write(p []byte) (int, error) {
if o.w == nil {
return 0, io.ErrClosedPipe
}
return o.w.Write(p)
}
func (o writerOutput) Println(a ...any) {
if o.w == nil {
return
}
fmt.Fprintln(o.w, a...)
}
func (o writerOutput) Printf(format string, a ...any) {
if o.w == nil {
return
}
fmt.Fprintf(o.w, format, a...)
}

58
bonfire/root.go Normal file
View File

@@ -0,0 +1,58 @@
package bonfire
import (
"io"
"os"
"github.com/spf13/cobra"
)
// NewRoot builds the shared cobra root used by the summer tool and app binaries.
// It accepts command values rather than a party registry to avoid an import cycle.
func NewRoot(name string, commands []Command, out io.Writer) *cobra.Command {
if out == nil {
out = os.Stdout
}
root := &cobra.Command{
Use: name,
SilenceUsage: true,
SilenceErrors: true,
CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: true,
},
}
root.SetOut(out)
root.SetErr(out)
for _, command := range commands {
root.AddCommand(wrap(command, out))
}
return root
}
func wrap(c Command, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: c.Name,
Short: c.Description,
Args: cobra.ArbitraryArgs,
RunE: func(cmd *cobra.Command, args []string) error {
if c.Run == nil {
return nil
}
writer := out
if cmd != nil {
if w := cmd.OutOrStdout(); w != nil {
writer = w
}
}
return c.Run(cmd.Context(), cobraInput{cmd: cmd, spec: c, args: args}, writerOutput{w: writer})
},
}
for _, flag := range c.Flags {
if flag.Shorthand != "" {
cmd.Flags().StringP(flag.Name, flag.Shorthand, flag.Default, flag.Description)
continue
}
cmd.Flags().String(flag.Name, flag.Default, flag.Description)
}
return cmd
}