mukan-ignite/ignite/pkg/swagger-combine/swagger-combine.go
Mukan Erkin Törük c32551b6f7
Some checks failed
Docs Deploy / build_and_deploy (push) Has been cancelled
Generate Docs / cli (push) Has been cancelled
Generate Config Doc / cli (push) Has been cancelled
Go formatting / go-formatting (push) Has been cancelled
Check links / markdown-link-check (push) Has been cancelled
Integration / pre-test (push) Has been cancelled
Integration / test on (push) Has been cancelled
Integration / status (push) Has been cancelled
Lint / Lint Go code (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:24 +03:00

121 lines
2.8 KiB
Go

package swaggercombine
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"github.com/go-openapi/analysis"
"github.com/go-openapi/loads"
"github.com/go-openapi/spec"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors"
)
// Config represent swagger-combine config.
type Config struct {
spec *spec.Swagger
specs []*spec.Swagger
}
// New create a mew swagger combine config.
func New(title, name string) *Config {
return &Config{
spec: &spec.Swagger{
SwaggerProps: spec.SwaggerProps{
ID: name,
Swagger: "2.0",
Info: &spec.Info{
InfoProps: spec.InfoProps{
Description: fmt.Sprintf("Chain %s REST API", name),
Title: title,
Contact: &spec.ContactInfo{ContactInfoProps: spec.ContactInfoProps{Name: name}},
},
},
Definitions: make(spec.Definitions),
},
},
specs: make([]*spec.Swagger, 0),
}
}
// AddSpec adds a new OpenAPI spec to Config by path in the fs and unique id of spec.
func (c *Config) AddSpec(id, path string, makeUnique bool) error {
baseDoc, err := loads.Spec(path)
if err != nil {
return errors.Wrapf(err, "failed to load spec from path %s", path)
}
spec := baseDoc.Spec()
if makeUnique {
for i, specPath := range spec.Paths.Paths {
if specPath.Get != nil {
specPath.Get.ID = id + specPath.Get.ID
}
if specPath.Post != nil {
specPath.Post.ID = id + specPath.Post.ID
}
spec.Paths.Paths[i] = specPath
}
}
c.specs = append(c.specs, c.mergeTags(c.mergeDefinitions(spec)))
return nil
}
// mergeDefinitions merge spec definitions with main spec and erase the spec definition.
func (c *Config) mergeDefinitions(m *spec.Swagger) *spec.Swagger {
for k, v := range m.Definitions {
if _, exists := c.spec.Definitions[k]; exists {
continue
}
c.spec.Definitions[k] = v
}
m.Definitions = nil
return m
}
// mergeTags merge spec tags with main spec and erase the spec tag.
func (c *Config) mergeTags(m *spec.Swagger) *spec.Swagger {
for _, v := range m.Tags {
found := false
for _, vv := range c.spec.Tags {
if v.Name == vv.Name {
found = true
break
}
}
if found {
continue
}
c.spec.Tags = append(c.spec.Tags, v)
}
m.Tags = nil
return m
}
// Combine combines openapi specs into one and saves to out path.
func (c *Config) Combine(out string) error {
sort.Slice(c.specs, func(a, b int) bool { return c.specs[a].ID < c.specs[b].ID })
errs := analysis.Mixin(c.spec, c.specs...)
if len(errs) > 0 {
return errors.Errorf("invalid mix specs: %s", strings.Join(errs, ", "))
}
specJSON, err := c.spec.MarshalJSON()
if err != nil {
return err
}
// ensure out dir exists.
outDir := filepath.Dir(out)
if err := os.MkdirAll(outDir, 0o766); err != nil {
return err
}
if err = os.WriteFile(out, specJSON, 0o600); err != nil {
return errors.Wrapf(err, "failed to write combined spec to file %s", out)
}
return nil
}