Skip to content
This repository was archived by the owner on Apr 29, 2026. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 42 additions & 9 deletions cmd/gen/simplify/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"fmt"
"os"

"github.com/doordash-oss/oapi-codegen-dd/v3/pkg/codegen"
"github.com/mockzilla/connexions/v2/internal/files"
"github.com/mockzilla/connexions/v2/pkg/typedef"
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi/datamodel"
"go.yaml.in/yaml/v4"
)

var (
flagConfig string
flagOutput string
flagKeepOptional int
flagMinOptionalProperties int
Expand All @@ -29,14 +32,17 @@ func init() {
fmt.Fprintf(os.Stderr, " - Removes optional properties with union types\n")
fmt.Fprintf(os.Stderr, " - Reduces required union properties to single variant (first variant)\n")
fmt.Fprintf(os.Stderr, " - Removes all extension fields (x-*) and examples\n")
fmt.Fprintf(os.Stderr, " - Optionally limits number of optional properties per schema\n\n")
fmt.Fprintf(os.Stderr, " - Optionally limits number of optional properties per schema\n")
fmt.Fprintf(os.Stderr, " - With -config: applies oapi-codegen-dd filter+overlay+prune\n")
fmt.Fprintf(os.Stderr, " BEFORE simplification (filter paths/tags/operation-ids,\n")
fmt.Fprintf(os.Stderr, " apply OpenAPI Overlay 1.0 deltas, drop dangling refs)\n\n")
fmt.Fprintf(os.Stderr, "Options:\n")
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nExamples:\n")
fmt.Fprintf(os.Stderr, " # Simplify unions and keep 5 optional properties per schema (default)\n")
fmt.Fprintf(os.Stderr, " go run %s openapi.yml\n\n", cmdPath)
fmt.Fprintf(os.Stderr, " # Simplify and save to file\n")
fmt.Fprintf(os.Stderr, " go run %s -output simplified.yml openapi.yml\n\n", cmdPath)
fmt.Fprintf(os.Stderr, " # Apply codegen.yml filter+overlay before simplification\n")
fmt.Fprintf(os.Stderr, " go run %s -config codegen.yml -output simplified.yml openapi.yml\n\n", cmdPath)
fmt.Fprintf(os.Stderr, " # Keep exactly 3 optional properties per schema\n")
fmt.Fprintf(os.Stderr, " go run %s -keep-optional 3 openapi.yml\n\n", cmdPath)
fmt.Fprintf(os.Stderr, " # Keep 1-3 optional properties (alphabetically first) per schema\n")
Expand All @@ -46,6 +52,7 @@ func init() {

func main() {
flag.BoolVar(&flagPrintUsage, "help", false, "Show this help and exit.")
flag.StringVar(&flagConfig, "config", "", "Path to oapi-codegen-dd codegen.yml. When set, the spec is run through filter+overlay+prune (using cfg.Filter and cfg.Overlay) before simplification.")
flag.StringVar(&flagOutput, "output", "", "Output file path. If not specified, outputs to stdout.")
flag.IntVar(&flagKeepOptional, "keep-optional", 5, "Keep exactly this many optional properties per schema. (default 5)")
flag.IntVar(&flagMinOptionalProperties, "min-optional-properties", 0, "Minimum number of optional properties to keep (overrides -keep-optional, used with -max-optional-properties).")
Expand Down Expand Up @@ -74,13 +81,9 @@ func main() {
os.Exit(1)
}

// Create document with config to skip circular reference check
docConfig := &datamodel.DocumentConfiguration{
SkipCircularReferenceCheck: true,
}
doc, err := libopenapi.NewDocumentWithConfiguration(specContents, docConfig)
doc, err := loadDocument(specContents)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing OpenAPI spec: %v\n", err)
fmt.Fprintf(os.Stderr, "Error loading OpenAPI spec: %v\n", err)
os.Exit(1)
}

Expand Down Expand Up @@ -127,3 +130,33 @@ func main() {
fmt.Print(string(rendered))
}
}

// loadDocument parses the OpenAPI bytes and, when -config is supplied,
// runs them through oapi-codegen-dd's filter + overlay + prune pipeline
// before simplification. Without -config it falls back to the historical
// behaviour: a plain libopenapi document with circular-ref check disabled.
func loadDocument(specContents []byte) (libopenapi.Document, error) {
if flagConfig == "" {
docConfig := &datamodel.DocumentConfiguration{
SkipCircularReferenceCheck: true,
}
return libopenapi.NewDocumentWithConfiguration(specContents, docConfig)
}

cfgBytes, err := os.ReadFile(flagConfig)
if err != nil {
return nil, fmt.Errorf("reading config %q: %w", flagConfig, err)
}

var cfg codegen.Configuration
if err := yaml.Unmarshal(cfgBytes, &cfg); err != nil {
return nil, fmt.Errorf("parsing config %q: %w", flagConfig, err)
}
cfg = cfg.WithDefaults()

// CreateDocument applies overlay (cfg.Overlay) -> filter (cfg.Filter)
// -> prune (drops dangling refs). Same pipeline used by `connexions
// gen-service`, so users can share one codegen.yml between codegen and
// simplify and get the same surface in both.
return codegen.CreateDocument(specContents, cfg)
}
Loading