fix(api): harden SDK generator inputs

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 13:43:07 +00:00
parent f6add24177
commit bfef7237cc
2 changed files with 85 additions and 3 deletions

View file

@ -11,6 +11,7 @@ import (
"os/exec"
"path/filepath"
"slices"
"strings"
coreio "dappco.re/go/core/io"
coreerr "dappco.re/go/core/log"
@ -54,20 +55,40 @@ type SDKGenerator struct {
//
// err := gen.Generate(context.Background(), "go")
func (g *SDKGenerator) Generate(ctx context.Context, language string) error {
if g == nil {
return coreerr.E("SDKGenerator.Generate", "generator is nil", nil)
}
if ctx == nil {
return coreerr.E("SDKGenerator.Generate", "context is nil", nil)
}
language = strings.TrimSpace(language)
generator, ok := supportedLanguages[language]
if !ok {
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 coreerr.E("SDKGenerator.Generate", "spec file not found: "+g.SpecPath, nil)
specPath := strings.TrimSpace(g.SpecPath)
if specPath == "" {
return coreerr.E("SDKGenerator.Generate", "spec path is required", nil)
}
if _, err := os.Stat(specPath); err != nil {
if os.IsNotExist(err) {
return coreerr.E("SDKGenerator.Generate", "spec file not found: "+specPath, nil)
}
return coreerr.E("SDKGenerator.Generate", "stat spec file", err)
}
outputBase := strings.TrimSpace(g.OutputDir)
if outputBase == "" {
return coreerr.E("SDKGenerator.Generate", "output directory is required", nil)
}
if !g.Available() {
return coreerr.E("SDKGenerator.Generate", "openapi-generator-cli not installed", nil)
}
outputDir := filepath.Join(g.OutputDir, language)
outputDir := filepath.Join(outputBase, language)
if err := coreio.Local.EnsureDir(outputDir); err != nil {
return coreerr.E("SDKGenerator.Generate", "create output directory", err)
}

View file

@ -59,6 +59,67 @@ func TestSDKGenerator_Bad_MissingSpec(t *testing.T) {
}
}
func TestSDKGenerator_Bad_EmptySpecPath(t *testing.T) {
gen := &api.SDKGenerator{
OutputDir: t.TempDir(),
}
err := gen.Generate(context.Background(), "go")
if err == nil {
t.Fatal("expected error for empty spec path, got nil")
}
if !strings.Contains(err.Error(), "spec path is required") {
t.Fatalf("expected error to contain 'spec path is required', got: %v", err)
}
}
func TestSDKGenerator_Bad_EmptyOutputDir(t *testing.T) {
specDir := t.TempDir()
specPath := filepath.Join(specDir, "spec.json")
if err := os.WriteFile(specPath, []byte(`{"openapi":"3.1.0"}`), 0o644); err != nil {
t.Fatalf("failed to write spec file: %v", err)
}
gen := &api.SDKGenerator{
SpecPath: specPath,
}
err := gen.Generate(context.Background(), "go")
if err == nil {
t.Fatal("expected error for empty output directory, got nil")
}
if !strings.Contains(err.Error(), "output directory is required") {
t.Fatalf("expected error to contain 'output directory is required', got: %v", err)
}
}
func TestSDKGenerator_Bad_NilContext(t *testing.T) {
gen := &api.SDKGenerator{
SpecPath: filepath.Join(t.TempDir(), "nonexistent.json"),
OutputDir: t.TempDir(),
}
err := gen.Generate(nil, "go")
if err == nil {
t.Fatal("expected error for nil context, got nil")
}
if !strings.Contains(err.Error(), "context is nil") {
t.Fatalf("expected error to contain 'context is nil', got: %v", err)
}
}
func TestSDKGenerator_Bad_NilReceiver(t *testing.T) {
var gen *api.SDKGenerator
err := gen.Generate(context.Background(), "go")
if err == nil {
t.Fatal("expected error for nil generator, got nil")
}
if !strings.Contains(err.Error(), "generator is nil") {
t.Fatalf("expected error to contain 'generator is nil', got: %v", err)
}
}
func TestSDKGenerator_Bad_MissingGenerator(t *testing.T) {
t.Setenv("PATH", t.TempDir())