go-build/pkg/sdk/generators/generator.go

122 lines
3.1 KiB
Go

// Package generators provides SDK code generators for different languages.
package generators
import (
"context"
"iter"
"runtime"
"sort"
"dappco.re/go/core"
"dappco.re/go/core/build/internal/ax"
)
// Options holds common generation options.
//
// opts := generators.Options{SpecPath: "docs/openapi.yaml", OutputDir: "sdk/typescript", PackageName: "@host-uk/api-client", Version: "1.0.0"}
type Options struct {
// SpecPath is the path to the OpenAPI spec file.
SpecPath string
// OutputDir is where to write the generated SDK.
OutputDir string
// PackageName is the package/module name.
PackageName string
// Version is the SDK version.
Version string
}
// Generator defines the interface for SDK generators.
//
// gen := generators.NewTypeScriptGenerator()
// err := gen.Generate(ctx, opts)
type Generator interface {
// Language returns the generator's target language identifier.
Language() string
// Generate creates SDK from OpenAPI spec.
Generate(ctx context.Context, opts Options) error
// Available checks if generator dependencies are installed.
Available() bool
// Install returns instructions for installing the generator.
Install() string
}
// Registry holds available generators.
//
// r := generators.NewRegistry()
type Registry struct {
generators map[string]Generator
}
// NewRegistry creates a registry with all available generators.
//
// r := generators.NewRegistry()
func NewRegistry() *Registry {
r := &Registry{
generators: make(map[string]Generator),
}
// Register the built-in generators so callers get a ready-to-use registry.
r.Register(NewTypeScriptGenerator())
r.Register(NewPythonGenerator())
r.Register(NewGoGenerator())
r.Register(NewPHPGenerator())
return r
}
// Get returns a generator by language.
//
// gen, ok := r.Get("typescript")
func (r *Registry) Get(lang string) (Generator, bool) {
g, ok := r.generators[lang]
return g, ok
}
// Register adds a generator to the registry.
//
// r.Register(generators.NewTypeScriptGenerator())
func (r *Registry) Register(g Generator) {
r.generators[g.Language()] = g
}
// Languages returns all registered language identifiers.
//
// langs := r.Languages() // → ["go", "php", "python", "typescript"]
func (r *Registry) Languages() []string {
var languages []string
for lang := range r.LanguagesIter() {
languages = append(languages, lang)
}
return languages
}
// LanguagesIter returns an iterator for all registered language identifiers.
//
// for lang := range r.LanguagesIter() { fmt.Println(lang) }
func (r *Registry) LanguagesIter() iter.Seq[string] {
return func(yield func(string) bool) {
// Sort keys for deterministic iteration
keys := make([]string, 0, len(r.generators))
for lang := range r.generators {
keys = append(keys, lang)
}
sort.Strings(keys)
for _, lang := range keys {
if !yield(lang) {
return
}
}
}
}
// dockerUserArgs returns Docker --user args for the current user on Unix systems.
// On Windows, Docker handles permissions differently, so no args are returned.
func dockerUserArgs() []string {
if runtime.GOOS == "windows" {
return nil
}
return []string{"--user", core.Sprintf("%d:%d", ax.Getuid(), ax.Getgid())}
}