// ©AngelaMos | 2026 // generate.go package cli import ( "fmt" "os" "github.com/spf13/cobra" "github.com/CarterPerez-dev/bomber/internal/parser" "github.com/CarterPerez-dev/bomber/internal/sbom" "github.com/CarterPerez-dev/bomber/internal/scanner" "github.com/CarterPerez-dev/bomber/internal/ui" ) var ( outputFile string sbomFormatFlag string ) var generateCmd = &cobra.Command{ Use: "generate [path]", Short: "Generate an SBOM document", Args: cobra.MaximumNArgs(1), RunE: runGenerate, } func init() { generateCmd.Flags().StringVarP( &outputFile, "output", "o", "", "output file (default: stdout)", ) generateCmd.Flags().StringVar( &sbomFormatFlag, "sbom-format", "cyclonedx", "SBOM format: spdx, cyclonedx", ) } func runGenerate(_ *cobra.Command, args []string) error { path := "." if len(args) > 0 { path = args[0] } reg := parser.NewRegistry() parser.RegisterAll(reg) s := scanner.New(reg) result, err := s.Scan(path) if err != nil { return err } if len(result.Graphs) == 0 { return fmt.Errorf("no ecosystems detected in %s", path) } var data []byte switch sbomFormatFlag { case "spdx": gen := sbom.NewSPDXGenerator() data, err = gen.Generate(result.Graphs) case "cyclonedx": gen := sbom.NewCycloneDXGenerator() data, err = gen.Generate(result.Graphs) default: return fmt.Errorf("unknown SBOM format: %s (use spdx or cyclonedx)", sbomFormatFlag) } if err != nil { return err } if outputFile != "" { if err := os.WriteFile(outputFile, data, 0o600); err != nil { return fmt.Errorf("write output: %w", err) } fmt.Fprintf(os.Stderr, " %s SBOM written to %s (%s)\n", ui.Check, outputFile, sbomFormatFlag) return nil } _, err = os.Stdout.Write(data) return err }