-
Notifications
You must be signed in to change notification settings - Fork 0
/
path.go
130 lines (121 loc) · 3.88 KB
/
path.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package chioas
import (
"github.com/go-andiamo/chioas/yaml"
"github.com/go-andiamo/urit"
"github.com/go-chi/chi/v5"
"sort"
"strings"
)
type Paths map[string]Path
func (ps Paths) writeYaml(opts *DocOptions, autoHeads bool, autoOptions bool, context string, w yaml.Writer) {
for _, p := range ps.flattenAndSort() {
p.writeYaml(opts, autoHeads, autoOptions, context, w)
}
}
// Path represents a path for both the router and the OAS spec
type Path struct {
// Methods is the methods on the path
Methods Methods
// Paths is the sub-paths of the path
Paths Paths
// Middlewares is any chi.Middlewares for the path
Middlewares chi.Middlewares
// ApplyMiddlewares is an optional function that returns chi.Middlewares for the path
ApplyMiddlewares ApplyMiddlewares
// Tag is the OAS tag of the path
//
// If this is an empty string and any ancestor Path.Tag is set then that ancestor tag is used
//
// The final tag is used by Method
Tag string
// PathParams is the OAS information about path params on this path
//
// Any path params introduced in the path are descended down the sub-paths and methods - any
// path params that are not documented will still be seen in the OAS spec for methods
PathParams PathParams
// HideDocs if set to true, hides this path (and descendants) from docs
HideDocs bool
// Disabled is an optional DisablerFunc that, when called, returns whether this path is to be disabled
//
// When a path is disabled it does not appear in docs and is not registered on the router
Disabled DisablerFunc
// Extensions is extension OAS yaml properties
Extensions Extensions
// Additional is any additional OAS spec yaml to be written
Additional Additional
// Comment is any comment(s) to appear in the OAS spec yaml
Comment string
// AutoOptionsMethod when set to true, automatically adds OPTIONS method for the path (and because Chioas knows the methods for each path can correctly set the Allow header)
//
// Note: If an OPTIONS method is already defined for the path then no OPTIONS method is automatically added
AutoOptionsMethod bool
}
type flatPath struct {
path string
ancestry []Path
def Path
tag string
}
func (p flatPath) writeYaml(opts *DocOptions, autoHeads bool, autoOptions bool, context string, w yaml.Writer) {
if p.def.Methods != nil && p.def.Methods.hasVisibleMethods(opts) {
template, err := urit.NewTemplate(p.path)
if err != nil {
w.SetError(err)
return
}
w.WritePathStart(context, template.Template(true)).
WriteComments(p.def.Comment)
if p.def.Methods != nil {
p.def.Methods.writeYaml(opts, autoHeads, autoOptions || p.def.AutoOptionsMethod, template, p.getPathParams(), p.tag, w)
}
writeExtensions(p.def.Extensions, w)
writeAdditional(p.def.Additional, p.def, w)
w.WriteTagEnd()
}
}
func (p flatPath) getPathParams() PathParams {
result := PathParams{}
for _, a := range p.ancestry {
if a.PathParams != nil {
for k, pp := range a.PathParams {
result[k] = pp
}
}
}
if p.def.PathParams != nil {
for k, pp := range p.def.PathParams {
result[k] = pp
}
}
return result
}
func (ps Paths) flattenAndSort() []flatPath {
result := pathsTraverse(nil, nil, nil, "", ps)
sort.Slice(result, func(i, j int) bool {
return result[i].path < result[j].path
})
return result
}
func pathsTraverse(collected []flatPath, parentPaths []string, ancestry []Path, tag string, paths Paths) []flatPath {
if paths != nil {
for path, def := range paths {
hidden := def.HideDocs
if !hidden && def.Disabled != nil {
hidden = def.Disabled()
}
if !hidden {
pps := append(parentPaths, path)
useTag := defaultTag(tag, def.Tag)
fp := flatPath{
path: strings.Join(pps, ""),
ancestry: ancestry,
def: def,
tag: useTag,
}
collected = append(collected, fp)
collected = pathsTraverse(collected, pps, append(ancestry, def), useTag, def.Paths)
}
}
}
return collected
}