output

package
v0.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package output defines events for the event/sink system

MessageEvent (use via sink.Emit with a MessageEvent):

  • SeverityInfo: Transient status ("Connecting...", "Validating...")
  • SeveritySuccess: Positive outcome ("Login successful")
  • SeverityNote: Informational outcome ("Not currently logged in")
  • SeverityWarning: Cautionary message ("Token expires soon")

SpinnerEvent (use via output.SpinnerStart/SpinnerStop constructors):

  • Show loading indicator during async operations
  • Always pair Start with Stop

ErrorEvent (use via sink.Emit with an ErrorEvent):

  • Structured errors with title, summary, detail, and recovery actions
  • Use for errors that need more than a single line

Index

Constants

View Source
const (
	StatusOK    = "ok"
	StatusError = "error"
)
View Source
const (
	LogSourceEmulator = "emulator"
	LogSourceBrew     = "brew"
	LogSourceNPM      = "npm"
)
View Source
const DefaultSpinnerMinDuration = 400 * time.Millisecond
View Source
const EnvelopeSchemaVersion = 1

EnvelopeSchemaVersion is the current version of the Envelope wire contract. Bump it only on a breaking change to the envelope itself or to a command's documented data shape; additive fields never require a bump.

View Source
const ErrorActionPrefix = "==> "

Variables

This section is empty.

Functions

func FormatEventLine

func FormatEventLine(event Event) (string, bool)

FormatEventLine converts an output event into a single display line.

func FormatPrompt added in v0.2.0

func FormatPrompt(prompt string, options []InputOption) string

FormatPrompt formats a prompt string with its options into a display line.

func FormatPromptLabels added in v0.4.0

func FormatPromptLabels(options []InputOption) string

FormatPromptLabels formats option labels into a suffix string. Returns " (label)" for a single option, " a/b" for multiple, or "" for none.

func FormatUptime added in v0.8.0

func FormatUptime(d time.Duration) string

func IsSilent added in v0.2.0

func IsSilent(err error) bool

IsSilent returns true if the error (or any error in its chain) is a SilentError.

func SuccessMarker added in v0.5.3

func SuccessMarker() string

Types

type AuthCompleteEvent added in v0.7.0

type AuthCompleteEvent struct{}

type AuthEvent added in v0.2.0

type AuthEvent struct {
	Preamble string
	Code     string
	URL      string
}

type ContainerStatusEvent

type ContainerStatusEvent struct {
	Phase     string // e.g., "pulling", "starting", "waiting", "ready"
	Container string
	Detail    string // optional extra info (e.g., container ID)
}

type DeferredEvent added in v0.13.0

type DeferredEvent struct {
	Inner Event
}

DeferredEvent wraps another event so that the TUI renders it after the interface exits rather than inline. Plain sinks format the inner event immediately.

type EmulatorResetEvent added in v0.17.0

type EmulatorResetEvent struct {
	Type string
	Name string
}

EmulatorResetEvent reports that the named emulator's in-memory state was reset.

type EmulatorStoppedEvent added in v0.17.0

type EmulatorStoppedEvent struct {
	Type        string
	Name        string
	DisplayName string
	WasRunning  bool
}

EmulatorStoppedEvent reports that a configured emulator was running and has been stopped. WasRunning is always true today (Stop returns an error before reaching this point otherwise) but is carried explicitly for JSON shape stability. DisplayName is precomputed by the caller (e.g. "LocalStack AWS Emulator"), matching InstanceInfoEvent.EmulatorName's existing precedent, so internal/output never needs to know how to derive it from Type.

type Envelope added in v0.17.0

type Envelope struct {
	SchemaVersion int            `json:"schemaVersion"`
	Command       string         `json:"command"`
	Status        string         `json:"status"`
	Data          any            `json:"data"`
	Warnings      []Warning      `json:"warnings"`
	Error         *EnvelopeError `json:"error"`
}

Envelope is the common result shape every JSON-capable command emits as a single object to stdout. Data and Warnings are always non-nil; Error is nil exactly when Status is "ok".

type EnvelopeAction added in v0.17.0

type EnvelopeAction struct {
	ID      string `json:"id"`
	Command string `json:"command"`
}

EnvelopeAction is a suggested remediation for an EnvelopeError. ID is a stable slug a script can switch on; Command is the literal shell command a human or script could run.

type EnvelopeError added in v0.17.0

type EnvelopeError struct {
	Code      ErrorCode        `json:"code"`
	Category  ErrorCategory    `json:"category"`
	Message   string           `json:"message"`
	Retryable bool             `json:"retryable"`
	Details   map[string]any   `json:"details,omitempty"`
	Actions   []EnvelopeAction `json:"actions,omitempty"`
}

EnvelopeError is the machine-readable error shape carried by a failed Envelope. Code is one of the constants in error_code.go and remains the primary, stable identifier; Category is an additive, coarse grouping of Code (~7 values vs. Code's ~28) for callers that only want to distinguish broad kinds of failure. Both Retryable and Category are static classifications of Code, never computed per instance.

type EnvelopeSink added in v0.17.0

type EnvelopeSink struct {
	// contains filtered or unexported fields
}

EnvelopeSink implements Sink by accumulating events into an Envelope instead of formatting lines. This accumulation step is not JSON-specific — it would be identical for any structured serialization; only the final marshal (driven by Format) differs. Presentational events (SpinnerEvent, ContainerStatusEvent, ProgressEvent, UserInputRequestEvent, ...) have no place in a single terminal result and are silently dropped.

func NewEnvelopeSink added in v0.17.0

func NewEnvelopeSink(format Format) *EnvelopeSink

NewEnvelopeSink returns an EnvelopeSink that serializes per format. Only FormatJSON exists today.

func (*EnvelopeSink) Emit added in v0.17.0

func (s *EnvelopeSink) Emit(event Event)

func (*EnvelopeSink) Result added in v0.17.0

func (s *EnvelopeSink) Result(command string, runErr error) Envelope

Result builds the final Envelope for command, given the error RunE returned. An error captured via an ErrorEvent (setError above) takes precedence; an error with no prior classification falls back to ErrInternal rather than leaving the envelope malformed.

type ErrorAction added in v0.2.0

type ErrorAction struct {
	Label string
	Value string
}

type ErrorCategory added in v0.17.0

type ErrorCategory string

ErrorCategory is a coarse, small-cardinality grouping of ErrorCode values, additive alongside Code (not a replacement for it — see design.md's naming decisions). A caller that only wants to distinguish broad kinds of failure (an environment problem vs. a usage problem vs. an auth problem) can switch on the ~7 Category values instead of the ~28 Code values; Code remains the primary, stable identifier for anything more specific.

const (
	// CategoryRuntime: something outside lstk's control (Docker, network, a
	// missing external binary) is the problem.
	CategoryRuntime ErrorCategory = "RUNTIME"
	// CategoryEmulator: the emulator isn't in the state this command needs.
	CategoryEmulator ErrorCategory = "EMULATOR"
	// CategoryAuth: identity, credentials, or license/entitlement.
	CategoryAuth ErrorCategory = "AUTH"
	// CategoryResource: a referenced thing (by name or ref) doesn't exist or
	// is invalid. Named generically, not e.g. "SNAPSHOT", so a future
	// non-snapshot resource error has somewhere to land without a new category.
	CategoryResource ErrorCategory = "RESOURCE"
	// CategoryConfig: lstk's own configuration is the problem.
	CategoryConfig ErrorCategory = "CONFIG"
	// CategoryUsage: the invocation itself needs to change (flags, args,
	// confirmation, capability).
	CategoryUsage ErrorCategory = "USAGE"
	// CategoryInternal: catch-all — unexpected failure or user-initiated
	// interruption.
	CategoryInternal ErrorCategory = "INTERNAL"
)

type ErrorCode added in v0.17.0

type ErrorCode string

ErrorCode is a stable, machine-readable identifier for a JSON envelope error. Values are documented in the error-codes OpenSpec capability; a call site with no applicable code SHALL use ErrInternal rather than inventing a new one.

const (
	ErrRuntimeUnavailable     ErrorCode = "RUNTIME_UNAVAILABLE"
	ErrImagePullFailed        ErrorCode = "IMAGE_PULL_FAILED"
	ErrEmulatorNotRunning     ErrorCode = "EMULATOR_NOT_RUNNING"
	ErrEmulatorAlreadyRunning ErrorCode = "EMULATOR_ALREADY_RUNNING"
	ErrEmulatorWrongType      ErrorCode = "EMULATOR_WRONG_TYPE"
	ErrEmulatorNotConfigured  ErrorCode = "EMULATOR_NOT_CONFIGURED"
	ErrEmulatorStartFailed    ErrorCode = "EMULATOR_START_FAILED"
	ErrAuthRequired           ErrorCode = "AUTH_REQUIRED"
	ErrAuthLoginFailed        ErrorCode = "AUTH_LOGIN_FAILED"
	ErrCredentialsMissing     ErrorCode = "CREDENTIALS_MISSING"
	ErrLicenseInvalid         ErrorCode = "LICENSE_INVALID"
	ErrLicenseUnsupportedTag  ErrorCode = "LICENSE_UNSUPPORTED_TAG"
	ErrSnapshotNotFound       ErrorCode = "SNAPSHOT_NOT_FOUND"
	ErrSnapshotInvalidRef     ErrorCode = "SNAPSHOT_INVALID_REF"
	ErrSnapshotRemoteError    ErrorCode = "SNAPSHOT_REMOTE_ERROR"
	ErrSnapshotBucketNotFound ErrorCode = "SNAPSHOT_BUCKET_NOT_FOUND"
	ErrConfigInvalid          ErrorCode = "CONFIG_INVALID"
	ErrConfigNotFound         ErrorCode = "CONFIG_NOT_FOUND"
	ErrIntegrationNotSetUp    ErrorCode = "INTEGRATION_NOT_SET_UP"
	ErrDependencyMissing      ErrorCode = "DEPENDENCY_MISSING"
	ErrDNSResolutionRequired  ErrorCode = "DNS_RESOLUTION_REQUIRED"
	ErrConfirmationRequired   ErrorCode = "CONFIRMATION_REQUIRED"
	ErrValidationError        ErrorCode = "VALIDATION_ERROR"
	ErrUsageError             ErrorCode = "USAGE_ERROR"
	ErrNotJSONCapable         ErrorCode = "NOT_JSON_CAPABLE"
	ErrNetworkError           ErrorCode = "NETWORK_ERROR"
	ErrCancelled              ErrorCode = "CANCELLED"
	ErrInternal               ErrorCode = "INTERNAL_ERROR"
)

func (ErrorCode) Category added in v0.17.0

func (c ErrorCode) Category() ErrorCategory

Category reports the code's static, coarse grouping. Every ErrorCode in allErrorCodes has one; a code missing from categoryByCode (which SHALL NOT happen) would report "" rather than panicking.

func (ErrorCode) Retryable added in v0.17.0

func (c ErrorCode) Retryable() bool

Retryable reports whether the identical invocation might succeed later without any change to arguments or environment. It is a static property of the code, documented in the error-codes capability's table.

type ErrorEvent added in v0.2.0

type ErrorEvent struct {
	Title   string
	Summary string
	Detail  string
	Actions []ErrorAction
	// Code classifies the error for JSON output. Empty means "not yet
	// classified" — EnvelopeSink falls back to ErrInternal. PlainSink and
	// TUISink ignore this field.
	Code ErrorCode
}

type Event

type Event interface {
	// contains filtered or unexported methods
}

Event is a sealed marker — only event types in this package implement it, so Sink.Emit rejects unknown types at compile time.

type ExitCodeError added in v0.17.0

type ExitCodeError struct {
	Err  error
	Code int
}

ExitCodeError wraps an error with the explicit process exit code it should produce, mirroring how *exec.ExitError already carries a proxied command's exit code. Used for the JSON envelope's exit-code conventions (0/1/2/3/4) — main.go checks for this type the same way it already checks for *exec.ExitError.

func (*ExitCodeError) Error added in v0.17.0

func (e *ExitCodeError) Error() string

func (*ExitCodeError) Unwrap added in v0.17.0

func (e *ExitCodeError) Unwrap() error

type Format added in v0.17.0

type Format string

Format identifies how an Envelope is serialized to bytes. FormatJSON is the only value implemented today; the type exists so a future serialization (e.g. YAML) is a new Format value and marshaler, not a rewrite of the EnvelopeSink accumulation logic below.

const FormatJSON Format = "json"

FormatJSON serializes an Envelope as compact JSON.

type InputOption

type InputOption struct {
	Key   string
	Label string
}

type InputResponse

type InputResponse struct {
	SelectedKey string
	Cancelled   bool
}

type InstallLocation added in v0.18.0

type InstallLocation struct {
	Path    string // location as found on PATH (what a shell would execute)
	Method  string // install method: "homebrew", "npm", or "binary"
	Running bool   // whether this entry is the currently running executable
}

InstallLocation describes one lstk executable found on PATH.

type InstanceInfoEvent added in v0.5.0

type InstanceInfoEvent struct {
	EmulatorName  string
	Version       string
	Host          string
	ContainerName string
	Uptime        time.Duration
	Persistence   bool
}

type JsonEmulatorEntry added in v0.17.0

type JsonEmulatorEntry interface {
	// contains filtered or unexported methods
}

JsonEmulatorEntry is a per-emulator entry in a command's data.emulators list. Sealed to this package so a new per-command shape (JsonStartedEmulator, ...) is added deliberately here, alongside the others, rather than accepted as a bare `any` at the call site.

type JsonEmulatorRef added in v0.17.0

type JsonEmulatorRef struct {
	Type string `json:"type"`
	Name string `json:"name"`
}

JsonEmulatorRef identifies an emulator.

type JsonStoppedEmulator added in v0.17.0

type JsonStoppedEmulator struct {
	JsonEmulatorRef
	WasRunning bool `json:"wasRunning"`
}

JsonStoppedEmulator is the per-emulator entry in `stop`'s data.emulators.

type LogLevel added in v0.5.2

type LogLevel int
const (
	LogLevelUnknown LogLevel = iota
	LogLevelDebug
	LogLevelInfo
	LogLevelWarn
	LogLevelError
)

type LogLineEvent added in v0.4.0

type LogLineEvent struct {
	Source string
	Line   string
	Level  LogLevel
}

type MessageEvent added in v0.2.0

type MessageEvent struct {
	Severity MessageSeverity
	Text     string
}

type MessageSeverity added in v0.2.0

type MessageSeverity int
const (
	SeverityInfo      MessageSeverity = iota
	SeveritySuccess                   // positive outcome
	SeverityNote                      // informational
	SeverityWarning                   // cautionary
	SeveritySecondary                 // subdued/decorative text
)

type MultipleInstallsEvent added in v0.18.0

type MultipleInstallsEvent struct {
	Installs []InstallLocation
}

MultipleInstallsEvent warns that more than one distinct lstk install was found on PATH. Installs are in PATH order, so the first entry is the one a shell resolves when the user types "lstk".

type PlainSink

type PlainSink struct {
	// contains filtered or unexported fields
}

func NewPlainSink

func NewPlainSink(out io.Writer) *PlainSink

func (*PlainSink) Emit added in v0.6.0

func (s *PlainSink) Emit(event Event)

func (*PlainSink) Err

func (s *PlainSink) Err() error

Err returns the first write error encountered, if any.

type PodSnapshotRemovedEvent added in v0.12.0

type PodSnapshotRemovedEvent struct {
	PodName string
}

type PodSnapshotSavedEvent added in v0.9.0

type PodSnapshotSavedEvent struct {
	PodName  string
	Version  int
	Services []string
	Size     int64
}

type ProgressEvent

type ProgressEvent struct {
	Container string
	LayerID   string
	Status    string
	Current   int64
	Total     int64
}

type PullSkippableEvent added in v0.15.0

type PullSkippableEvent struct {
	Image  string
	SkipCh chan<- struct{}
}

PullSkippableEvent signals that an in-flight image pull can be abandoned in favor of an already-present local image. The domain emits it once real layer download begins (interactive mode, with a local copy present); the TUI binds ESC during the pull to send on SkipCh, which the domain selects on to cancel the pull and fall back to the local image. Never emitted in non-interactive mode, so PlainSink never needs to answer it.

type RemoteSnapshotSavedEvent added in v0.15.0

type RemoteSnapshotSavedEvent struct {
	PodName  string
	Location string
	Version  int
	Services []string
	Size     int64
}

RemoteSnapshotSavedEvent reports a snapshot saved to a remote storage backend (e.g. an S3 bucket). Location is the user-facing remote target (e.g. an s3:// URL) and PodName is the snapshot's identity within that remote.

type ResourceSummaryEvent added in v0.5.0

type ResourceSummaryEvent struct {
	Resources int
	Services  int
}

type Sender

type Sender interface {
	Send(msg any)
}

Sender abstracts Bubble Tea's Program.Send to keep TUISink decoupled and testable.

type SilentError added in v0.2.0

type SilentError struct {
	Err error
}

SilentError wraps an error that has already been displayed to the user through the sink mechanism. Callers should check for this type and skip printing the error again.

func NewSilentError added in v0.2.0

func NewSilentError(err error) *SilentError

func (*SilentError) Error added in v0.2.0

func (e *SilentError) Error() string

func (*SilentError) Unwrap added in v0.2.0

func (e *SilentError) Unwrap() error

type Sink

type Sink interface {
	Emit(event Event)
}

type SinkFunc

type SinkFunc func(event Event)

func (SinkFunc) Emit added in v0.6.0

func (f SinkFunc) Emit(event Event)

type SnapshotLoadedEvent added in v0.10.0

type SnapshotLoadedEvent struct {
	Source   string   // display source shown to the user (e.g. "./snap.snapshot" or "pod:my-baseline")
	Services []string // services restored
}

type SnapshotResourceCount added in v0.13.0

type SnapshotResourceCount struct {
	Count int
	Noun  string
}

SnapshotResourceCount is a count of one resource kind, e.g. {Count: 3, Noun: "buckets"}.

type SnapshotResourceLine added in v0.13.0

type SnapshotResourceLine struct {
	Service string
	Counts  []SnapshotResourceCount
}

SnapshotResourceLine groups the resource counts of a single service.

type SnapshotShownEvent added in v0.13.0

type SnapshotShownEvent struct {
	Name              string
	Created           *time.Time
	Size              int64
	LocalStackVersion string
	Message           string
	Services          []string
	Resources         []SnapshotResourceLine
}

SnapshotShownEvent reports the metadata of a single cloud snapshot for the `snapshot show` command. Created is nil and Resources is empty when the platform has no value for them; the formatter omits those sections.

type SpinnerEvent added in v0.2.0

type SpinnerEvent struct {
	Active      bool
	Text        string
	MinDuration time.Duration // Minimum time spinner should display (0 = use default)
}

func SpinnerStart added in v0.6.0

func SpinnerStart(text string) SpinnerEvent

func SpinnerStartWithDuration added in v0.6.0

func SpinnerStartWithDuration(text string, minDuration time.Duration) SpinnerEvent

func SpinnerStop added in v0.6.0

func SpinnerStop() SpinnerEvent

type TUISink

type TUISink struct {
	// contains filtered or unexported fields
}

func NewTUISink

func NewTUISink(sender Sender) *TUISink

func (*TUISink) Emit added in v0.6.0

func (s *TUISink) Emit(event Event)

type TableEvent added in v0.5.0

type TableEvent struct {
	Headers []string
	Rows    [][]string
}

type UpdateAppliedEvent added in v0.17.0

type UpdateAppliedEvent struct {
	CurrentVersion string
	UpdatedVersion string
	Method         string
}

UpdateAppliedEvent reports that an update was downloaded and installed.

type UpdateCheckedEvent added in v0.17.0

type UpdateCheckedEvent struct {
	CurrentVersion string
	LatestVersion  string
	Available      bool
	DevBuild       bool
}

UpdateCheckedEvent reports the result of an update check. It always fires once per Check call — DevBuild, then Available, discriminate which of the three possible outcomes (dev build skipped the check / already up to date / an update is available) the formatter should render. LatestVersion is empty when DevBuild is true (the check never ran).

type UserInputRequestEvent

type UserInputRequestEvent struct {
	Prompt     string
	Options    []InputOption
	ResponseCh chan<- InputResponse
	Vertical   bool
}

type Warning added in v0.17.0

type Warning struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

Warning is a non-fatal notice surfaced alongside a successful result.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL