diff --git a/cmd/activity.go b/cmd/activity.go index b2be778..a9b27d9 100644 --- a/cmd/activity.go +++ b/cmd/activity.go @@ -49,6 +49,12 @@ var activityCmd = &cobra.Command{ Use: "activity", Short: "Export daily activity (steps, distance, calories, HR zones)", RunE: func(cmd *cobra.Command, args []string) error { + // Parse-level flag validation runs before any network call so an + // invalid --format exits non-zero hermetically (CONTRACT §4). + format, err := validateFormat(activityFormatFlag) + if err != nil { + return err + } since, err := sinceOrDefault(activitySinceFlag, 30) if err != nil { return err @@ -83,10 +89,6 @@ var activityCmd = &cobra.Command{ sort.Slice(all, func(i, j int) bool { return all[i].Date < all[j].Date }) - format, err := validateFormat(activityFormatFlag) - if err != nil { - return err - } switch format { case "json": return printJSON(all) diff --git a/cmd/intraday.go b/cmd/intraday.go index 3becff9..103a7f7 100644 --- a/cmd/intraday.go +++ b/cmd/intraday.go @@ -69,6 +69,12 @@ spo2_auto, steps and distance; native Withings trackers report steps and HR. Default window is the last 24h — intraday is dense; wider ranges are slow.`, RunE: func(cmd *cobra.Command, args []string) error { + // Parse-level flag validation runs before any network call so an + // invalid --format exits non-zero hermetically (CONTRACT §4). + format, err := validateFormat(intradayFormatFlag) + if err != nil { + return err + } since, err := sinceOrDefault(intradaySinceFlag, 1) if err != nil { return err @@ -124,10 +130,6 @@ Default window is the last 24h — intraday is dense; wider ranges are slow.`, sort.Slice(all, func(i, j int) bool { return all[i].Timestamp < all[j].Timestamp }) - format, err := validateFormat(intradayFormatFlag) - if err != nil { - return err - } switch format { case "json": return printJSON(all) diff --git a/cmd/measurements.go b/cmd/measurements.go index d75dda6..4faafe7 100644 --- a/cmd/measurements.go +++ b/cmd/measurements.go @@ -80,6 +80,12 @@ var measurementsCmd = &cobra.Command{ Use: "measurements", Short: "Export body measurements (weight, body fat, BP, etc.)", RunE: func(cmd *cobra.Command, args []string) error { + // Parse-level flag validation runs before any network call so an + // invalid --format exits non-zero hermetically (CONTRACT §4). + format, err := validateFormat(measurementsFormatFlag) + if err != nil { + return err + } since, err := sinceOrDefault(measurementsSinceFlag, 30) if err != nil { return err @@ -131,10 +137,6 @@ var measurementsCmd = &cobra.Command{ sort.Slice(rows, func(i, j int) bool { return rows[i].Date.Before(rows[j].Date) }) - format, err := validateFormat(measurementsFormatFlag) - if err != nil { - return err - } switch format { case "json": return printJSON(rows) diff --git a/cmd/sleep.go b/cmd/sleep.go index b1a20f2..f23e91a 100644 --- a/cmd/sleep.go +++ b/cmd/sleep.go @@ -44,6 +44,12 @@ var sleepCmd = &cobra.Command{ Use: "sleep", Short: "Export nightly sleep summaries", RunE: func(cmd *cobra.Command, args []string) error { + // Parse-level flag validation runs before any network call so an + // invalid --format exits non-zero hermetically (CONTRACT §4). + format, err := validateFormat(sleepFormatFlag) + if err != nil { + return err + } since, err := sinceOrDefault(sleepSinceFlag, 30) if err != nil { return err @@ -110,10 +116,6 @@ var sleepCmd = &cobra.Command{ sort.Slice(all, func(i, j int) bool { return all[i].StartDate < all[j].StartDate }) - format, err := validateFormat(sleepFormatFlag) - if err != nil { - return err - } switch format { case "json": return printJSON(all) diff --git a/cmd/workouts.go b/cmd/workouts.go index 0c65178..e465e1a 100644 --- a/cmd/workouts.go +++ b/cmd/workouts.go @@ -95,6 +95,12 @@ var workoutsCmd = &cobra.Command{ Use: "workouts", Short: "Export workouts (runs, walks, bikes, etc.)", RunE: func(cmd *cobra.Command, args []string) error { + // Parse-level flag validation runs before any network call so an + // invalid --format exits non-zero hermetically (CONTRACT §4). + format, err := validateFormat(workoutsFormatFlag) + if err != nil { + return err + } since, err := sinceOrDefault(workoutsSinceFlag, 90) if err != nil { return err @@ -131,10 +137,6 @@ var workoutsCmd = &cobra.Command{ sort.Slice(all, func(i, j int) bool { return all[i].StartDate < all[j].StartDate }) - format, err := validateFormat(workoutsFormatFlag) - if err != nil { - return err - } switch format { case "json": return printJSON(all)