Fix doc generator, backport learnings from typescript generator (#61)

* Fix gen

* more fixes

* Nuking things

* Run always, only publish when master

* Remove printline
This commit is contained in:
Janos Dobronszki
2021-02-03 15:05:14 +00:00
committed by GitHub
parent ac1c00e421
commit bc30a8ad81
5 changed files with 1446 additions and 1105 deletions

View File

@@ -259,37 +259,39 @@ func saveSpec(originalMarkDown []byte, contentDir, serviceName string, spec *ope
func schemaToMap(spec *openapi3.SchemaRef, schemas map[string]*openapi3.SchemaRef) map[string]interface{} {
var recurse func(props map[string]*openapi3.SchemaRef) map[string]interface{}
getAtomic := func(v *openapi3.SchemaRef) interface{} {
switch v.Value.Type {
case "string":
if len(v.Value.Description) > 0 {
return strings.Replace(v.Value.Description, "\n", ".", -1)
} else {
return v.Value.Type
}
case "number":
return 1
case "boolean":
return true
}
return "UNKOWN TYPE " + v.Value.Type
}
recurse = func(props map[string]*openapi3.SchemaRef) map[string]interface{} {
ret := map[string]interface{}{}
for k, v := range props {
k = strcase.SnakeCase(k)
//v.Value.
if v.Value.Type == "object" {
// @todo identify what is a slice and what is not!
// currently the openapi converter messes this up
// see redoc html output
ret[k] = recurse(v.Value.Properties)
continue
}
if v.Value.Type == "array" {
// @todo identify what is a slice and what is not!
// currently the openapi converter messes this up
// see redoc html output
ret[k] = []interface{}{recurse(v.Value.Properties)}
if v.Value.Items.Value.Type != "object" {
ret[k] = []interface{}{getAtomic(v.Value.Items)}
} else {
ret[k] = []interface{}{recurse(v.Value.Items.Value.Properties)}
}
continue
}
switch v.Value.Type {
case "string":
if len(v.Value.Description) > 0 {
ret[k] = strings.Replace(v.Value.Description, "\n", ".", -1)
} else {
ret[k] = v.Value.Type
}
case "number":
ret[k] = 1
case "boolean":
ret[k] = true
}
ret[k] = getAtomic(v)
}
return ret

View File

@@ -10,7 +10,6 @@ import (
"os/exec"
"path/filepath"
"strings"
"text/template"
"github.com/Masterminds/semver/v3"
"github.com/getkin/kin-openapi/openapi3"
@@ -172,144 +171,6 @@ func main() {
}
}
type specType struct {
name string
tag string
includeReadme bool
filePostFix string
titlePostFix string
template string
}
var specTypes = []specType{
{
name: "default markdown",
tag: "Readme",
filePostFix: ".md",
template: defTempl,
includeReadme: true,
},
}
func saveFile(tsDir string, serviceName string, spec *openapi3.Swagger) error {
for _, v := range specTypes {
fmt.Println("Processing ", v.name)
contentFile := filepath.Join(tsDir, serviceName+".ts")
fi, err := os.OpenFile(contentFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777)
if err != nil {
return err
}
tmpl, err := template.New("test").Funcs(template.FuncMap{
"toLower": func(s string) string {
return strings.ToLower(s)
},
"params": func(p openapi3.Parameters) string {
ls := ""
for _, v := range p {
//if v.Value.In == "body" {
bs, _ := v.MarshalJSON()
ls += string(bs) + ", "
//}
}
return ls
},
// @todo should take SpecRef here not RequestBodyRef
"schemaJSON": func(prepend int, ref string) string {
for k, v := range spec.Components.Schemas {
// ie. #/components/requestBodies/PostsSaveRequest contains
// SaveRequest, can't see any other way to correlate
if strings.HasSuffix(ref, k) {
bs, _ := json.MarshalIndent(schemaToMap(v, spec.Components.Schemas), "", strings.Repeat(" ", prepend)+" ")
// last line wont get prepended so we fix that here
parts := strings.Split(string(bs), "\n")
// skip if it's only 1 line, ie it's '{}'
if len(parts) <= 1 {
return string(bs)
}
parts[len(parts)-1] = parts[len(parts)-1]
return strings.Join(parts, "\n")
}
}
return "Schema related to " + ref + " not found"
},
"schemaDescription": func(ref string) string {
for k, v := range spec.Components.Schemas {
// ie. #/components/requestBodies/PostsSaveRequest contains
// SaveRequest, can't see any other way to correlate
if strings.HasSuffix(ref, k) {
return v.Value.Description
}
}
return "Schema related to " + ref + " not found"
},
// turn chat/Chat/History
// to Chat History
"titleize": func(s string) string {
parts := strings.Split(s, "/")
if len(parts) > 2 {
return strings.Join(parts[2:], " ")
}
return strings.Join(parts, " ")
},
"firstResponseRef": func(rs openapi3.Responses) string {
return rs.Get(200).Ref
},
}).Parse(v.template)
if err != nil {
panic(err)
}
err = tmpl.Execute(fi, spec)
if err != nil {
return err
}
}
return nil
}
func schemaToMap(spec *openapi3.SchemaRef, schemas map[string]*openapi3.SchemaRef) map[string]interface{} {
var recurse func(props map[string]*openapi3.SchemaRef) map[string]interface{}
recurse = func(props map[string]*openapi3.SchemaRef) map[string]interface{} {
ret := map[string]interface{}{}
for k, v := range props {
k = strcase.SnakeCase(k)
//v.Value.
if v.Value.Type == "object" {
// @todo identify what is a slice and what is not!
// currently the openapi converter messes this up
// see redoc html output
ret[k] = recurse(v.Value.Properties)
continue
}
if v.Value.Type == "array" {
// @todo identify what is a slice and what is not!
// currently the openapi converter messes this up
// see redoc html output
ret[k] = []interface{}{recurse(v.Value.Properties)}
continue
}
switch v.Value.Type {
case "string":
if len(v.Value.Description) > 0 {
ret[k] = strings.Replace(v.Value.Description, "\n", ".", -1)
} else {
ret[k] = v.Value.Type
}
case "number":
ret[k] = 1
case "boolean":
ret[k] = true
}
}
return ret
}
return recurse(spec.Value.Properties)
}
func schemaToTs(title string, spec *openapi3.SchemaRef) string {
var recurse func(props map[string]*openapi3.SchemaRef, level int) string
@@ -356,12 +217,6 @@ func schemaToTs(title string, spec *openapi3.SchemaRef) string {
return "export interface " + title + " {\n" + recurse(spec.Value.Properties, 1) + "}"
}
const defTempl = `
import { components } from './{{ .Info.Title | toLower }}_schema';
export interface types extends components {};
`
// CopyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherise, attempt to create a hard link
// between the two files. If that fail, copy the file contents from src to dst.