package commandkit import ( "io" "strings" configkit "gitea.maximumdirect.net/eric/ConfigKit" ) // OutcomeKind classifies the result of a command invocation. type OutcomeKind string const ( // OutcomeSuccess indicates that the operation completed successfully. OutcomeSuccess OutcomeKind = "success" // OutcomeUsage indicates invalid command syntax or declared input. OutcomeUsage OutcomeKind = "usage" // OutcomeOperational indicates an operational failure. OutcomeOperational OutcomeKind = "operational" // OutcomeDomain indicates a result classified by application domain logic. OutcomeDomain OutcomeKind = "domain" ) // DeliveryState describes whether CommandKit completed diagnostic delivery. type DeliveryState string const ( // DeliveryNone indicates that no diagnostic delivery was attempted. DeliveryNone DeliveryState = "none" // DeliveryComplete indicates that diagnostic delivery completed. DeliveryComplete DeliveryState = "complete" // DeliveryIncomplete indicates that diagnostic delivery did not complete. DeliveryIncomplete DeliveryState = "incomplete" ) // Diagnostic is a deferred message written to an invocation's error stream. // // Write is called by CommandKit's diagnostic delivery path. It should return // any error encountered while writing. A nil Write function has no output. type Diagnostic struct { // Severity classifies the diagnostic using ConfigKit's public severity type. Severity configkit.Severity // Write writes the diagnostic to the supplied writer. Write func(io.Writer) error } // Outcome is the classified result of an operation. // // Cause records the operation error. DeliveryError records an error encountered // while presenting diagnostics or reports; it is kept separate from Cause so // both failures remain inspectable. Outcome does not implement error. type Outcome struct { // Kind classifies the result. Kind OutcomeKind // Status is the suggested process status for this result. Status int // Domain names the application-defined classification when Kind is // OutcomeDomain. Domain string // Cause is the error returned by the operation. Cause error // DeliveryError is an error encountered while writing a report or // diagnostics. DeliveryError error // DiagnosticDelivery records whether diagnostic writing completed. Its zero // value is treated as DeliveryNone by invocation coordination. DiagnosticDelivery DeliveryState // ReportIncomplete is true when a failed write left a report incomplete. ReportIncomplete bool // Diagnostics are delivered in slice order by invocation coordination. Diagnostics []Diagnostic } // Success returns a successful outcome with status 0. func Success() Outcome { return Outcome{Kind: OutcomeSuccess, Status: 0, DiagnosticDelivery: DeliveryNone} } // Usage returns a usage outcome with status 2 and the supplied cause. func Usage(cause error) Outcome { return Outcome{Kind: OutcomeUsage, Status: 2, Cause: cause, DiagnosticDelivery: DeliveryNone} } // Failure returns an operational outcome with status 1 and the supplied cause. func Failure(cause error) Outcome { return Outcome{Kind: OutcomeOperational, Status: 1, Cause: cause, DiagnosticDelivery: DeliveryNone} } // Domain returns an application-domain outcome preserving the supplied name, // status, and cause. func Domain(name string, status int, cause error) Outcome { return Outcome{Kind: OutcomeDomain, Status: status, Domain: name, Cause: cause, DiagnosticDelivery: DeliveryNone} } // MessageDiagnostic returns a diagnostic that writes message followed by a // newline. The writer's error is returned to the caller. func MessageDiagnostic(severity configkit.Severity, message string) Diagnostic { return Diagnostic{ Severity: severity, Write: func(w io.Writer) error { _, err := io.WriteString(w, strings.TrimSuffix(message, "\n")+"\n") return err }, } }