mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-12 03:05:14 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user