feat(14.3-01): add summer new with a starter route and relative go.work

- build.NewApp writes sm-<name>-app: go.mod with a relative framework
  replace, go.work, summer.yaml, config/ and a starter plugin
- make:plugin gains an opt-in starter route (GET /{$}) in the same
  routes.go template; plain make:plugin output is unchanged
- plugin:add writes go.work use paths relative to the go.work directory
- bonfire accepts new as a bare tool command name
This commit is contained in:
Jakub Zych
2026-10-08 11:37:53 +02:00
parent 86fcd5d4fd
commit 7bc955a0c2
10 changed files with 423 additions and 15 deletions

View File

@@ -11,7 +11,7 @@ bonfire is the console layer of SummerCMS. Plugins and framework modules describ
## Features
- Command values with a description, positional arguments (`bonfire.Arg`) and string flags (`bonfire.Flag`), collected from plugins or the tool itself.
- Command name validation: plugin commands must use the `namespace:verb` form (for example `blog:import`); `build`, `dev`, `serve` and `migrate` are the only bare names accepted. Invalid names make `bonfire.NewRoot` fail with `bonfire.ErrCommandName`.
- Command name validation: plugin commands must use the `namespace:verb` form (for example `blog:import`); `build`, `dev`, `new`, `serve` and `migrate` are the only bare names accepted. Invalid names make `bonfire.NewRoot` fail with `bonfire.ErrCommandName`.
- Usage strings and argument-count checks derived from the declared arguments (`<name>` for required, `[name]` for optional).
- Scalar flags, bare flags (`bonfire.Flag.Bare`, so `--force` alone stores `true`) and ordered repeatable flags (`bonfire.Flag.Repeatable`, read back through `bonfire.Input.Flags`).
- Styled status lines: `bonfire.Output.Info`, `bonfire.Output.Success`, `bonfire.Output.Warning` and `bonfire.Output.Error` (the last one writes to the error stream).

View File

@@ -109,7 +109,7 @@ func (in cobraInput) Flag(name string) (string, bool) {
func validCommandName(name string) bool {
switch name {
case "build", "dev", "serve", "migrate":
case "build", "dev", "new", "serve", "migrate":
return true
}
ns, verb, ok := strings.Cut(name, ":")

View File

@@ -6,7 +6,7 @@ import (
)
func TestValidBareRuntimeCommandNames(t *testing.T) {
for _, name := range []string{"serve", "migrate", "migrate:rollback", "migrate:status", "build", "dev"} {
for _, name := range []string{"serve", "migrate", "migrate:rollback", "migrate:status", "build", "dev", "new"} {
if _, err := NewRoot("app", []Command{{Name: name}}, io.Discard); err != nil {
t.Fatalf("%s: %v", name, err)
}