cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
at main 94 lines 2.2 kB view raw
1// package shared contains constants used across the codebase 2package shared 3 4import ( 5 "errors" 6 "fmt" 7 "io" 8 "os" 9 "path/filepath" 10 "time" 11 12 "github.com/charmbracelet/log" 13) 14 15var ( 16 ErrConfig error = fmt.Errorf("configuration error") 17) 18 19func ConfigError(m string, err error) error { 20 return errors.Join(ErrConfig, fmt.Errorf("%s: %w", m, err)) 21} 22 23func IsConfigError(err error) bool { 24 return errors.Is(err, ErrConfig) 25} 26 27// CompoundWriter writes every payload to two sinks: 28// 1. a primary sink (typically [os.Stdout] or [os.Stderr]) 29// 2. a secondary sink (typically [*os.File]) 30// 31// It satisfies io.Writer. 32type CompoundWriter struct { 33 primary io.Writer 34 secondary io.Writer 35} 36 37// New creates a new [CompoundWriter] 38func New(primary io.Writer, secondary io.Writer) *CompoundWriter { 39 return &CompoundWriter{ 40 primary: primary, 41 secondary: secondary, 42 } 43} 44 45func LogWithStdErr(w io.WriteCloser) *CompoundWriter { 46 return New(os.Stderr, w) 47} 48 49func LogWithStdOut(w io.WriteCloser) *CompoundWriter { 50 return New(os.Stdout, w) 51} 52 53// Write writes p to both instances of [io.Writer] 54func (cw *CompoundWriter) Write(p []byte) (int, error) { 55 var err error 56 var n1, n2 int 57 58 if n1, err = cw.primary.Write(p); err != nil { 59 return n1, err 60 } 61 if n2, err = cw.secondary.Write(p); err != nil { 62 return n2, err 63 } 64 return len(p), nil 65} 66 67func FallbackLogger() *log.Logger { 68 return log.NewWithOptions(os.Stderr, log.Options{ 69 Prefix: "[DEBUG]", 70 ReportTimestamp: true, 71 ReportCaller: true, 72 TimeFormat: time.Kitchen, 73 Level: log.DebugLevel, 74 }) 75} 76 77// NewDebugLoggerWithFile creates a new debug logger that writes to both stderr and a log file 78func NewDebugLoggerWithFile(configDir string) *log.Logger { 79 logger := FallbackLogger() 80 logsDir := filepath.Join(configDir, "logs") 81 if err := os.MkdirAll(logsDir, 0755); err != nil { 82 return logger 83 } 84 85 logFile := filepath.Join(logsDir, fmt.Sprintf("publication_%s.log", time.Now().Format("2006-01-02"))) 86 file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) 87 if err != nil { 88 return logger 89 } 90 91 w := LogWithStdErr(file) 92 logger.SetOutput(w) 93 return logger 94}