/
meta.go
186 lines (183 loc) Β· 7 KB
/
meta.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package dsl
import (
"goa.design/goa/v3/eval"
"goa.design/goa/v3/expr"
)
// Meta defines a set of key/value pairs that can be assigned to an object. Each
// value consists of a slice of strings so that multiple invocation of the Meta
// function on the same target using the same key builds up the slice.
//
// Meta may appear in attributes, result types, endpoints, responses, services
// and API definitions.
//
// While keys can have any value the following names have special meanings:
//
// - "type:generate:force" forces the code generation for the type it is defined
// on. By default goa only generates types that are used explicitly by the
// service methods. The value is a slice of strings that lists the names of the
// services for which to generate the struct. The struct is generated for all
// services if left empty.
//
// package design
//
// var _ = Service("service1", func() { ... })
// var _ = Service("service2", func() { ... })
//
// var Unused = Type("Unused", func() {
// Attribute("name", String)
// Meta("type:generate:force", "service1", "service2")
// })
//
// - "struct:error:name" DEPRECATED, use ErrorName instead.
//
// - "struct:pkg:path" overrides where the Go type generated for the enclosing
// user type definition is generated. Both the file location and Go package name
// are overridden. The file location is computed by appending the location of
// the gen folder with the string given as second argument to Meta. So for
// example Meta("struct:pkg:path", "foo/bar") will generate the Go type in the
// file "gen/foo/bar/<name>.go" where <name> is the name of the type.
// Additionally the package name is computed by taking the base path of the
// provided location ("bar" in the prior example). The example below causes the
// Go type declaration for MyType to live in the file gen/types/mytype.go with
// the package name "types":
//
// package design
//
// var MyType = Type("MyType", func() {
// Attribute("name")
// Meta("struct:pkg:path", "types")
// })
//
// - "struct:field:name" overrides the Go struct field name generated by default
// by goa. Applicable to attributes only.
//
// var MyType = Type("MyType", func() {
// Attribute("ssn", String, "User SSN", func() {
// Meta("struct:field:name", "SSN")
// })
// })
//
// - "struct:field:type" overrides the Go struct field type specified in the
// design, with one caveat; if the type would have been a pointer (such as its
// not Required) the new type will also be a pointer. Applicable to attributes
// only. The import path of the type should be passed in as the second
// parameter, if needed. If the default imported package name conflicts with
// another, you can override that as well with the third parameter.
//
// var MyType = Type("BigOleMessage", func() {
// Attribute("type", String, "Type of big payload")
// Attribute("bigPayload", String, "Don't parse it if you don't have to",func() {
// Meta("struct:field:type","json.RawMessage","encoding/json")
// })
// Attribute("id", String, func() {
// Meta("struct:field:type","bison.ObjectId", "github.com/globalsign/mgo/bson", "bison")
// })
// })
//
//
// - "struct:tag:xxx" sets a generated Go struct field tag and overrides tags
// that Goa would otherwise set. If the metadata value is a slice then the
// strings are joined with the space character as separator. Applicable to
// attributes only.
//
// var MyType = Type("MyType", func() {
// Attribute("ssn", String, "User SSN", func() {
// Meta("struct:tag:json", "SSN,omitempty")
// Meta("struct:tag:xml", "SSN,omitempty")
// })
// })
//
// - "swagger:generate" DEPRECATED, use "openapi:generate" instead.
//
// - "openapi:generate" specifies whether OpenAPI specification should be
// generated. Defaults to true. Applicable to services, methods and file
// servers.
//
// var _ = Service("MyService", func() {
// Meta("openapi:generate", "false")
// })
//
// - "swagger:summary" DEPRECATED, use "openapi:summary" instead
//
// - "openapi:summary" sets the OpenAPI operation summary field. Applicable to
// methods.
//
// var _ = Service("MyService", func() {
// Method("MyMethod", func() {
// Meta("openapi:summary", "Summary of MyMethod")
// })
// })
//
// - "swagger:example" DEPRECATED, use "openapi:example" instead
//
// - "openapi:example" specifies whether to generate random example. Defaults to
// true. Applicable to API (applies to all attributes) or individual attributes.
//
// var _ = API("MyAPI", func() {
// Meta("openapi:example", "false")
// })
//
// - "swagger:tag:xxx" DEPRECATED, use "openapi:tag:xxx" instead
//
// - "openapi:tag:xxx" sets the OpenAPI object field tag xxx. Applicable to
// services and methods.
//
// var _ = Service("MyService", func() {
// Method("MyMethod", func() {
// Meta("openapi:tag:Backend")
// Meta("openapi:tag:Backend:desc", "Description of Backend")
// Meta("openapi:tag:Backend:url", "http://example.com")
// Meta("openapi:tag:Backend:url:desc", "See more docs here")
// Meta("openapi:tag:Backend:extension:x-data", `{"foo":"bar"}`)
// })
// })
//
// - "swagger:extension:xxx" DEPRECATED, use "openapi:extension:xxx" instead
//
// - "openapi:extension:xxx" sets the OpenAPI extensions xxx. The value can be
// any valid JSON. Applicable to API (OpenAPI info and tag objects), Service
// (OpenAPI paths object), Method (OpenAPI path-item object), Route (OpenAPI
// operation object), Param (OpenAPI parameter object), Response (OpenAPI
// response object) and Security (OpenAPI security-scheme object). See
// https://github.com/OAI/OpenAPI-Specification/blob/master/guidelines/EXTENSIONS.md.
//
// var _ = API("MyAPI", func() {
// Meta("openapi:extension:x-api", `{"foo":"bar"}`)
// })
//
func Meta(name string, value ...string) {
appendMeta := func(meta expr.MetaExpr, name string, value ...string) expr.MetaExpr {
if meta == nil {
meta = make(map[string][]string)
}
meta[name] = append(meta[name], value...)
return meta
}
switch e := eval.Current().(type) {
case *expr.APIExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.AttributeExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.ResultTypeExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.MethodExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.ServiceExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.HTTPServiceExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.HTTPEndpointExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.RouteExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.HTTPFileServerExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case *expr.HTTPResponseExpr:
e.Meta = appendMeta(e.Meta, name, value...)
case expr.CompositeExpr:
att := e.Attribute()
att.Meta = appendMeta(att.Meta, name, value...)
default:
eval.IncompatibleDSL()
}
}