schemas.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright 2020 Google LLC. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, softwis
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //
  15. package wellknown
  16. import (
  17. v3 "github.com/google/gnostic/openapiv3"
  18. "google.golang.org/protobuf/reflect/protoreflect"
  19. )
  20. func NewStringSchema() *v3.SchemaOrReference {
  21. return &v3.SchemaOrReference{
  22. Oneof: &v3.SchemaOrReference_Schema{
  23. Schema: &v3.Schema{Type: "string"}}}
  24. }
  25. func NewBooleanSchema() *v3.SchemaOrReference {
  26. return &v3.SchemaOrReference{
  27. Oneof: &v3.SchemaOrReference_Schema{
  28. Schema: &v3.Schema{Type: "boolean"}}}
  29. }
  30. func NewBytesSchema() *v3.SchemaOrReference {
  31. return &v3.SchemaOrReference{
  32. Oneof: &v3.SchemaOrReference_Schema{
  33. Schema: &v3.Schema{Type: "string", Format: "bytes"}}}
  34. }
  35. func NewIntegerSchema(format string) *v3.SchemaOrReference {
  36. return &v3.SchemaOrReference{
  37. Oneof: &v3.SchemaOrReference_Schema{
  38. Schema: &v3.Schema{Type: "integer", Format: format}}}
  39. }
  40. func NewNumberSchema(format string) *v3.SchemaOrReference {
  41. return &v3.SchemaOrReference{
  42. Oneof: &v3.SchemaOrReference_Schema{
  43. Schema: &v3.Schema{Type: "number", Format: format}}}
  44. }
  45. func NewEnumSchema(enum_type *string, field protoreflect.FieldDescriptor) *v3.SchemaOrReference {
  46. schema := &v3.Schema{Format: "enum"}
  47. if enum_type != nil && *enum_type == "string" {
  48. schema.Type = "string"
  49. schema.Enum = make([]*v3.Any, 0, field.Enum().Values().Len())
  50. for i := 0; i < field.Enum().Values().Len(); i++ {
  51. schema.Enum = append(schema.Enum, &v3.Any{
  52. Yaml: string(field.Enum().Values().Get(i).Name()),
  53. })
  54. }
  55. } else {
  56. schema.Type = "integer"
  57. }
  58. return &v3.SchemaOrReference{
  59. Oneof: &v3.SchemaOrReference_Schema{
  60. Schema: schema}}
  61. }
  62. func NewListSchema(item_schema *v3.SchemaOrReference) *v3.SchemaOrReference {
  63. return &v3.SchemaOrReference{
  64. Oneof: &v3.SchemaOrReference_Schema{
  65. Schema: &v3.Schema{
  66. Type: "array",
  67. Items: &v3.ItemsItem{SchemaOrReference: []*v3.SchemaOrReference{item_schema}},
  68. },
  69. },
  70. }
  71. }
  72. // google.api.HttpBody will contain POST body data
  73. // This is based on how Envoy handles google.api.HttpBody
  74. func NewGoogleApiHttpBodySchema() *v3.SchemaOrReference {
  75. return &v3.SchemaOrReference{
  76. Oneof: &v3.SchemaOrReference_Schema{
  77. Schema: &v3.Schema{Type: "string"}}}
  78. }
  79. // google.protobuf.Timestamp is serialized as a string
  80. func NewGoogleProtobufTimestampSchema() *v3.SchemaOrReference {
  81. return &v3.SchemaOrReference{
  82. Oneof: &v3.SchemaOrReference_Schema{
  83. Schema: &v3.Schema{Type: "string", Format: "date-time"}}}
  84. }
  85. // google.protobuf.Duration is serialized as a string
  86. func NewGoogleProtobufDurationSchema() *v3.SchemaOrReference {
  87. return &v3.SchemaOrReference{
  88. Oneof: &v3.SchemaOrReference_Schema{
  89. // From: https://github.com/protocolbuffers/protobuf/blob/ece5ef6b9b6fa66ef4638335612284379ee4548f/src/google/protobuf/duration.proto
  90. // In JSON format, the Duration type is encoded as a string rather than an
  91. // object, where the string ends in the suffix "s" (indicating seconds) and
  92. // is preceded by the number of seconds, with nanoseconds expressed as
  93. // fractional seconds. For example, 3 seconds with 0 nanoseconds should be
  94. // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
  95. // be expressed in JSON format as "3.000000001s", and 3 seconds and 1
  96. // microsecond should be expressed in JSON format as "3.000001s".
  97. //
  98. // The fields of message google.protobuf.Duration are further described as:
  99. // "int64 seconds"
  100. // Signed seconds of the span of time. Must be from -315,576,000,000
  101. // to +315,576,000,000 inclusive. Note: these bounds are computed from:
  102. // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
  103. // `int32 nanos`
  104. // Signed fractions of a second at nanosecond resolution of the span
  105. // of time. Durations less than one second are represented with a 0
  106. // `seconds` field and a positive or negative `nanos` field. For durations
  107. // of one second or more, a non-zero value for the `nanos` field must be
  108. // of the same sign as the `seconds` field. Must be from -999,999,999
  109. // to +999,999,999 inclusive.
  110. //
  111. // This leads to the regex below limiting range from -315.576,000,000s to 315,576,000,000s
  112. // allowing -0.999,999,999s to 0.999,999,999s in the floating precision range.
  113. // That full range cannot be expressed precisly in float64 as demonstrated in
  114. // the example at https://go.dev/play/p/XNtuhwdyu8Y for your reference.
  115. // So the well known type google.protobuf.Duration needs a string.
  116. //
  117. // Please note that JSON schemas duration format is NOT the same, as that uses
  118. // a different syntax starting with "P", supports daylight saving times and other
  119. // different features, so it is NOT compatible.
  120. Schema: &v3.Schema{
  121. Type: "string",
  122. Pattern: `^-?(?:0|[1-9][0-9]{0,11})(?:\.[0-9]{1,9})?s$`,
  123. Description: "Represents a a duration between -315,576,000,000s and 315,576,000,000s (around 10000 years). Precision is in nanoseconds. 1 nanosecond is represented as 0.000000001s",
  124. },
  125. },
  126. }
  127. }
  128. // google.type.Date is serialized as a string
  129. func NewGoogleTypeDateSchema() *v3.SchemaOrReference {
  130. return &v3.SchemaOrReference{
  131. Oneof: &v3.SchemaOrReference_Schema{
  132. Schema: &v3.Schema{Type: "string", Format: "date"}}}
  133. }
  134. // google.type.DateTime is serialized as a string
  135. func NewGoogleTypeDateTimeSchema() *v3.SchemaOrReference {
  136. return &v3.SchemaOrReference{
  137. Oneof: &v3.SchemaOrReference_Schema{
  138. Schema: &v3.Schema{Type: "string", Format: "date-time"}}}
  139. }
  140. // google.protobuf.FieldMask masks is serialized as a string
  141. func NewGoogleProtobufFieldMaskSchema() *v3.SchemaOrReference {
  142. return &v3.SchemaOrReference{
  143. Oneof: &v3.SchemaOrReference_Schema{
  144. Schema: &v3.Schema{Type: "string", Format: "field-mask"}}}
  145. }
  146. // google.protobuf.Struct is equivalent to a JSON object
  147. func NewGoogleProtobufStructSchema() *v3.SchemaOrReference {
  148. return &v3.SchemaOrReference{
  149. Oneof: &v3.SchemaOrReference_Schema{
  150. Schema: &v3.Schema{Type: "object"}}}
  151. }
  152. // google.protobuf.Value is handled specially
  153. // See here for the details on the JSON mapping:
  154. //
  155. // https://developers.google.com/protocol-buffers/docs/proto3#json
  156. //
  157. // and here:
  158. //
  159. // https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Value
  160. func NewGoogleProtobufValueSchema(name string) *v3.NamedSchemaOrReference {
  161. return &v3.NamedSchemaOrReference{
  162. Name: name,
  163. Value: &v3.SchemaOrReference{
  164. Oneof: &v3.SchemaOrReference_Schema{
  165. Schema: &v3.Schema{
  166. Description: "Represents a dynamically typed value which can be either null, a number, a string, a boolean, a recursive struct value, or a list of values.",
  167. },
  168. },
  169. },
  170. }
  171. }
  172. // google.protobuf.Any is handled specially
  173. // See here for the details on the JSON mapping:
  174. //
  175. // https://developers.google.com/protocol-buffers/docs/proto3#json
  176. func NewGoogleProtobufAnySchema(name string) *v3.NamedSchemaOrReference {
  177. return &v3.NamedSchemaOrReference{
  178. Name: name,
  179. Value: &v3.SchemaOrReference{
  180. Oneof: &v3.SchemaOrReference_Schema{
  181. Schema: &v3.Schema{
  182. Type: "object",
  183. Description: "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message.",
  184. Properties: &v3.Properties{
  185. AdditionalProperties: []*v3.NamedSchemaOrReference{
  186. {
  187. Name: "@type",
  188. Value: &v3.SchemaOrReference{
  189. Oneof: &v3.SchemaOrReference_Schema{
  190. Schema: &v3.Schema{
  191. Type: "string",
  192. Description: "The type of the serialized message.",
  193. },
  194. },
  195. },
  196. },
  197. },
  198. },
  199. AdditionalProperties: &v3.AdditionalPropertiesItem{
  200. Oneof: &v3.AdditionalPropertiesItem_Boolean{
  201. Boolean: true,
  202. },
  203. },
  204. },
  205. },
  206. },
  207. }
  208. }
  209. // google.rpc.Status is handled specially
  210. func NewGoogleRpcStatusSchema(name string, any_name string) *v3.NamedSchemaOrReference {
  211. return &v3.NamedSchemaOrReference{
  212. Name: name,
  213. Value: &v3.SchemaOrReference{
  214. Oneof: &v3.SchemaOrReference_Schema{
  215. Schema: &v3.Schema{
  216. Type: "object",
  217. Description: "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).",
  218. Properties: &v3.Properties{
  219. AdditionalProperties: []*v3.NamedSchemaOrReference{
  220. {
  221. Name: "code",
  222. Value: &v3.SchemaOrReference{
  223. Oneof: &v3.SchemaOrReference_Schema{
  224. Schema: &v3.Schema{
  225. Type: "integer",
  226. Format: "int32",
  227. Description: "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
  228. },
  229. },
  230. },
  231. },
  232. {
  233. Name: "message",
  234. Value: &v3.SchemaOrReference{
  235. Oneof: &v3.SchemaOrReference_Schema{
  236. Schema: &v3.Schema{
  237. Type: "string",
  238. Description: "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.",
  239. },
  240. },
  241. },
  242. },
  243. {
  244. Name: "details",
  245. Value: &v3.SchemaOrReference{
  246. Oneof: &v3.SchemaOrReference_Schema{
  247. Schema: &v3.Schema{
  248. Type: "array",
  249. Items: &v3.ItemsItem{
  250. SchemaOrReference: []*v3.SchemaOrReference{
  251. {
  252. Oneof: &v3.SchemaOrReference_Reference{
  253. Reference: &v3.Reference{
  254. XRef: "#/components/schemas/" + any_name,
  255. },
  256. },
  257. },
  258. },
  259. },
  260. Description: "A list of messages that carry the error details. There is a common set of message types for APIs to use.",
  261. },
  262. },
  263. },
  264. },
  265. },
  266. },
  267. },
  268. },
  269. },
  270. }
  271. }
  272. func NewGoogleProtobufMapFieldEntrySchema(value_field_schema *v3.SchemaOrReference) *v3.SchemaOrReference {
  273. return &v3.SchemaOrReference{
  274. Oneof: &v3.SchemaOrReference_Schema{
  275. Schema: &v3.Schema{Type: "object",
  276. AdditionalProperties: &v3.AdditionalPropertiesItem{
  277. Oneof: &v3.AdditionalPropertiesItem_SchemaOrReference{
  278. SchemaOrReference: value_field_schema,
  279. },
  280. },
  281. },
  282. },
  283. }
  284. }