From d510af404d2801658af9797d1db011e4d36b673e Mon Sep 17 00:00:00 2001 From: Snider Date: Mon, 16 Mar 2026 21:33:44 +0000 Subject: [PATCH] refactor(api): replace fmt.Errorf and os.* with coreerr.E and coreio.Local Replace all fmt.Errorf/errors.New in production code with coreerr.E() from go-log. Replace os.MkdirAll with coreio.Local.EnsureDir and os.Remove with coreio.Local.Delete. Promote go-io and go-log to direct dependencies in go.mod. Co-Authored-By: Virgil --- cmd/api/cmd_sdk.go | 15 +++++++++------ codegen.go | 13 ++++++++----- export.go | 18 ++++++++++-------- go.mod | 4 ++-- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/cmd/api/cmd_sdk.go b/cmd/api/cmd_sdk.go index 6d23b84..6a5f8b9 100644 --- a/cmd/api/cmd_sdk.go +++ b/cmd/api/cmd_sdk.go @@ -10,6 +10,9 @@ import ( "forge.lthn.ai/core/cli/pkg/cli" + coreio "forge.lthn.ai/core/go-io" + coreerr "forge.lthn.ai/core/go-log" + goapi "forge.lthn.ai/core/api" ) @@ -23,7 +26,7 @@ func addSDKCommand(parent *cli.Command) { cmd := cli.NewCommand("sdk", "Generate client SDKs from OpenAPI spec", "", func(cmd *cli.Command, args []string) error { if lang == "" { - return fmt.Errorf("--lang is required. Supported: %s", strings.Join(goapi.SupportedLanguages(), ", ")) + return coreerr.E("sdk.Generate", "--lang is required. Supported: "+strings.Join(goapi.SupportedLanguages(), ", "), nil) } // If no spec file provided, generate one to a temp file. @@ -39,13 +42,13 @@ func addSDKCommand(parent *cli.Command) { tmpFile, err := os.CreateTemp("", "openapi-*.json") if err != nil { - return fmt.Errorf("create temp spec file: %w", err) + return coreerr.E("sdk.Generate", "create temp spec file", err) } - defer os.Remove(tmpFile.Name()) + defer coreio.Local.Delete(tmpFile.Name()) if err := goapi.ExportSpec(tmpFile, "json", builder, groups); err != nil { tmpFile.Close() - return fmt.Errorf("generate spec: %w", err) + return coreerr.E("sdk.Generate", "generate spec", err) } tmpFile.Close() specFile = tmpFile.Name() @@ -61,7 +64,7 @@ func addSDKCommand(parent *cli.Command) { fmt.Fprintln(os.Stderr, "openapi-generator-cli not found. Install with:") fmt.Fprintln(os.Stderr, " brew install openapi-generator (macOS)") fmt.Fprintln(os.Stderr, " npm install @openapitools/openapi-generator-cli -g") - return fmt.Errorf("openapi-generator-cli not installed") + return coreerr.E("sdk.Generate", "openapi-generator-cli not installed", nil) } // Generate for each language. @@ -72,7 +75,7 @@ func addSDKCommand(parent *cli.Command) { } fmt.Fprintf(os.Stderr, "Generating %s SDK...\n", l) if err := gen.Generate(context.Background(), l); err != nil { - return fmt.Errorf("generate %s: %w", l, err) + return coreerr.E("sdk.Generate", "generate "+l, err) } fmt.Fprintf(os.Stderr, " Done: %s/%s/\n", output, l) } diff --git a/codegen.go b/codegen.go index c3d25fe..39b203b 100644 --- a/codegen.go +++ b/codegen.go @@ -11,6 +11,9 @@ import ( "os/exec" "path/filepath" "slices" + + coreio "forge.lthn.ai/core/go-io" + coreerr "forge.lthn.ai/core/go-log" ) // Supported SDK target languages. @@ -45,16 +48,16 @@ type SDKGenerator struct { func (g *SDKGenerator) Generate(ctx context.Context, language string) error { generator, ok := supportedLanguages[language] if !ok { - return fmt.Errorf("unsupported language %q: supported languages are %v", language, SupportedLanguages()) + return coreerr.E("SDKGenerator.Generate", fmt.Sprintf("unsupported language %q: supported languages are %v", language, SupportedLanguages()), nil) } if _, err := os.Stat(g.SpecPath); os.IsNotExist(err) { - return fmt.Errorf("spec file not found: %s", g.SpecPath) + return coreerr.E("SDKGenerator.Generate", "spec file not found: "+g.SpecPath, nil) } outputDir := filepath.Join(g.OutputDir, language) - if err := os.MkdirAll(outputDir, 0o755); err != nil { - return fmt.Errorf("create output directory: %w", err) + if err := coreio.Local.EnsureDir(outputDir); err != nil { + return coreerr.E("SDKGenerator.Generate", "create output directory", err) } args := g.buildArgs(generator, outputDir) @@ -63,7 +66,7 @@ func (g *SDKGenerator) Generate(ctx context.Context, language string) error { cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { - return fmt.Errorf("openapi-generator-cli failed for %s: %w", language, err) + return coreerr.E("SDKGenerator.Generate", "openapi-generator-cli failed for "+language, err) } return nil diff --git a/export.go b/export.go index bb233ce..d4e3614 100644 --- a/export.go +++ b/export.go @@ -4,12 +4,14 @@ package api import ( "encoding/json" - "fmt" "io" "os" "path/filepath" "gopkg.in/yaml.v3" + + coreio "forge.lthn.ai/core/go-io" + coreerr "forge.lthn.ai/core/go-log" ) // ExportSpec generates the OpenAPI spec and writes it to w. @@ -17,7 +19,7 @@ import ( func ExportSpec(w io.Writer, format string, builder *SpecBuilder, groups []RouteGroup) error { data, err := builder.Build(groups) if err != nil { - return fmt.Errorf("build spec: %w", err) + return coreerr.E("ExportSpec", "build spec", err) } switch format { @@ -28,28 +30,28 @@ func ExportSpec(w io.Writer, format string, builder *SpecBuilder, groups []Route // Unmarshal JSON then re-marshal as YAML. var obj any if err := json.Unmarshal(data, &obj); err != nil { - return fmt.Errorf("unmarshal spec: %w", err) + return coreerr.E("ExportSpec", "unmarshal spec", err) } enc := yaml.NewEncoder(w) enc.SetIndent(2) if err := enc.Encode(obj); err != nil { - return fmt.Errorf("encode yaml: %w", err) + return coreerr.E("ExportSpec", "encode yaml", err) } return enc.Close() default: - return fmt.Errorf("unsupported format %q: use \"json\" or \"yaml\"", format) + return coreerr.E("ExportSpec", "unsupported format "+format+": use \"json\" or \"yaml\"", nil) } } // ExportSpecToFile writes the spec to the given path. // The parent directory is created if it does not exist. func ExportSpecToFile(path, format string, builder *SpecBuilder, groups []RouteGroup) error { - if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return fmt.Errorf("create directory: %w", err) + if err := coreio.Local.EnsureDir(filepath.Dir(path)); err != nil { + return coreerr.E("ExportSpecToFile", "create directory", err) } f, err := os.Create(path) if err != nil { - return fmt.Errorf("create file: %w", err) + return coreerr.E("ExportSpecToFile", "create file", err) } defer f.Close() return ExportSpec(f, format, builder, groups) diff --git a/go.mod b/go.mod index 248d211..a716e10 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.26.0 require ( forge.lthn.ai/core/cli v0.3.1 + forge.lthn.ai/core/go-io v0.1.2 + forge.lthn.ai/core/go-log v0.0.4 github.com/99designs/gqlgen v0.17.88 github.com/andybalholm/brotli v1.2.0 github.com/casbin/casbin/v2 v2.135.0 @@ -40,8 +42,6 @@ require ( forge.lthn.ai/core/go-crypt v0.1.7 // indirect forge.lthn.ai/core/go-i18n v0.1.4 // indirect forge.lthn.ai/core/go-inference v0.1.4 // indirect - forge.lthn.ai/core/go-io v0.1.2 // indirect - forge.lthn.ai/core/go-log v0.0.4 // indirect forge.lthn.ai/core/go-process v0.2.3 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/ProtonMail/go-crypto v1.4.0 // indirect