---
layout: 'page'
uri: '/framework/presentation/console'
position: 3
slug: 'framework-presentation-console'
parent: 'framework-presentation'
navTitle: 'Console'
title: 'Console'
description: 'Cobra CLI -- root command, serve, seed a create-user subcommand.'
---

# Console

## Proč

CLI je druhý vstupní bod aplikace vedle HTTP serveru. Cobra umožňuje snadno přidávat další příkazy (migrace, seedy, one-off skripty) bez změny serveru.

## Jak

Balíček `presentation/console/`. Root command `app` s podpříkazy:

```
app [command]

Available Commands:
  serve         Start the HTTP server
  seed          Seed the database with default data
  create-user   Create a user (any role -- defaults to admin)
  help          Help about any command
```

Před každým subcommandem se volá `Application.Run()`, který nejprve aplikuje pending Goose migrace -- migrace tedy doběhnou i při `seed`/`create-user`, ne jen při `serve`.

### Serve command

```go
// presentation/console/serve.go

type ServeCommand struct {
    server    *server.Server
    scheduler *scheduler.Scheduler
}

func (c *ServeCommand) Command() *cobra.Command {
    return &cobra.Command{
        Use:   "serve",
        Short: "Start the HTTP server",
        RunE: func(cmd *cobra.Command, args []string) error {
            ctx := cmd.Context()

            schedulerDone := make(chan struct{})
            go func() {
                defer close(schedulerDone)
                c.scheduler.Run(ctx)
            }()

            serverErr := c.server.Start(ctx)
            <-schedulerDone
            return serverErr
        },
    }
}
```

`ServeCommand` orchestrátor: scheduler + HTTP server sdílí jeden `ctx` z `signal.NotifyContext`. SIGTERM drainuje obojí v tandemu. Detaily v [Scheduler](/framework/infrastructure/scheduler) a [HTTP Server](/framework/presentation/http-server).

Spuštění:

```bash
./bin/app serve
# Nebo:
make serve
```

### Seed command

```go
// presentation/console/seed.go

type SeedCommand struct {
    seeder shared.Seeder
}

func (c *SeedCommand) Command() *cobra.Command {
    return &cobra.Command{
        Use:   "seed",
        Short: "Seed the database with default data",
        RunE: func(cmd *cobra.Command, args []string) error {
            return c.seeder.Seed(cmd.Context())
        },
    }
}
```

Spuštění:

```bash
./bin/app seed   # vytvoří admin účet (heslo z APP_SEED_ADMIN_PASSWORD) pokud ještě neexistuje
```

### Create-user command

```go
// presentation/console/create_user.go

type CreateUserCommand struct {
    handler *usercmd.CreateUserHandler
}
```

Bypassuje bus (žádný auth context potřeba) a volá přímo `*usercmd.CreateUserHandler.Handle()` -- recykluje stejnou validaci, hashing a unique-nickname check jako HTTP API. V handleru `EventCollectorFromContext(ctx)` vrátí throwaway collector (bus tu nepřipravuje per-request collector), takže emitované domain eventy se tiše zahodí — pro CLI to je žádoucí.

```bash
./bin/app create-user -n alice -p secret12              # admin (default)
./bin/app create-user -n bob -p secret12 -e b@x -r user # user, s emailem
```

Flagy: `-n/--nickname` (povinné), `-p/--password` (povinné), `-e/--email` (volitelné), `-r/--role` (`admin` default, `user` alternativa).


## Detaily

- Root command (`root.go`) registruje všechny subcommandy.
- Každý příkaz dostává závislosti přes DI (Wire) a závisí na doménové interfaces (např. `shared.Seeder`), případně na application handlerech (`*usercmd.CreateUserHandler`) -- ne na konkrétní infrastruktuře.
- Komponenta `console` v `.go-arch-lint.yml` má `mayDependOn: [server, scheduler, worker, config, database, application, bus]` -- CLI volá application handlery stejně jako HTTP handlery a `serve` co-spouští scheduler + worker.
- Nové příkazy se přidávají stejným patternem: struct s `Command() *cobra.Command` metodou, registrace v root commandu.

---

[← Handlers & Middleware](/framework/presentation/http-handlers.md) | [Infrastructure →](/framework/infrastructure.md)
