diff --git a/README.md b/README.md index be995e1..a41ad1c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ -

Fizz is a wrapper for Gin based on gadgeto/tonic.
It generates wrapping gin-compatible handlers that do all the repetitive work and wrap the call to your handlers. It can also generates an almost complete OpenAPI 3 specification of your API.
-
-
-
+
+
+
-
+
@@ -17,7 +16,7 @@
### Getting started
-To create a Fizz instance, you can pass an existing *Gin* engine to `fizz.NewFromEngine`, or use `fizz.New` that will use a new default *Gin* engine.
+To create a Fizz instance, you can pass an existing _Gin_ engine to `fizz.NewFromEngine`, or use `fizz.New` that will use a new default _Gin_ engine.
```go
engine := gin.Default()
@@ -27,6 +26,7 @@ f := fizz.NewFromEngine(engine)
```
A Fizz instance implements the `http.HandlerFunc` interface, which means it can be used as the base handler of your HTTP server.
+
```go
srv := &http.Server{
Addr: ":4242",
@@ -37,7 +37,7 @@ srv.ListenAndServe()
### Handlers
-Fizz abstracts the `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `HEAD` and `TRACE` methods of a *Gin* engine. These functions accept a variadic list of handlers as the last parameter, but since Fizz relies on *tonic* to retrieve the informations required to generate the *OpenAPI* specification of the operation, **only one of the handlers registered MUST be wrapped with Tonic**.
+Fizz abstracts the `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `HEAD` and `TRACE` methods of a _Gin_ engine. These functions accept a variadic list of handlers as the last parameter, but since Fizz relies on _tonic_ to retrieve the informations required to generate the _OpenAPI_ specification of the operation, **only one of the handlers registered MUST be wrapped with Tonic**.
In the following example, the `BarHandler` is a simple middleware that will be executed before the `FooHandler`, but the generator will use the input/output type of the `FooHandler` to generate the specification of the operation.
@@ -49,7 +49,7 @@ fizz := fizz.New()
fizz.GET("/foo/bar", nil, BarHandler, tonic.Handler(FooHandler, 200))
```
-However, registering only standard handlers that follow the `gin.HandlerFunc` signature is accepted, but the *OpenAPI* generator will ignore the operation and it won't appear in the specification.
+However, registering only standard handlers that follow the `gin.HandlerFunc` signature is accepted, but the _OpenAPI_ generator will ignore the operation and it won't appear in the specification.
### Operation informations
@@ -116,10 +116,12 @@ fizz.XInternal()
```
**NOTES:**
-* `fizz.InputModel` allows to override the operation input regardless of how the handler implementation really binds the request parameters. It is the developer responsibility to ensure that the binding matches the OpenAPI specification.
-* The first argument of the `fizz.Reponse` method which represents an HTTP status code is of type *string* because the spec accept the value `default`. See the [Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responsesObject) documentation for more informations.
+
+- `fizz.InputModel` allows to override the operation input regardless of how the handler implementation really binds the request parameters. It is the developer responsibility to ensure that the binding matches the OpenAPI specification.
+- The first argument of the `fizz.Reponse` method which represents an HTTP status code is of type _string_ because the spec accept the value `default`. See the [Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responsesObject) documentation for more informations.
To help you declare additional headers, predefined variables for Go primitives types that you can use as the third argument of the `fizz.Header` method are available:
+
```go
var (
Integer int32
@@ -136,11 +138,12 @@ var (
### Groups
-Exactly like you would do with *Gin*, you can create a group of routes using the method `Group`. Unlike *Gin* own method, Fizz's one takes two other optional arguments, `name` and `description`. These parameters will be used to create a tag in the **OpenAPI** specification that will be applied to all the routes added to the group.
+Exactly like you would do with _Gin_, you can create a group of routes using the method `Group`. Unlike _Gin_ own method, Fizz's one takes two other optional arguments, `name` and `description`. These parameters will be used to create a tag in the **OpenAPI** specification that will be applied to all the routes added to the group.
```go
grp := f.Group("/subpath", "MyGroup", "Group description", middlewares...)
```
+
If the `name` parameter is empty, the tag won't be created and it won't be used.
Subgroups of subgroups can be created to an infinite depth, according yo your needs.
@@ -157,24 +160,28 @@ bar.GET("/:barID", nil, tonic.Handler(MyBarHandler, 200))
```
The `Use` method can be used with groups to register middlewares after their creation.
+
```go
grp.Use(middleware1, middleware2, ...)
```
## Tonic
-The subpackage *tonic* handles path/query/header/body parameters binding in a single consolidated input object which allows you to remove all the boilerplate code that retrieves and tests the presence of various parameters. The *OpenAPI* generator make use of the input/output types informations of a tonic-wrapped handler reported by *tonic* to document the operation in the specification.
+The subpackage _tonic_ handles path/query/header/body parameters binding in a single consolidated input object which allows you to remove all the boilerplate code that retrieves and tests the presence of various parameters. The _OpenAPI_ generator make use of the input/output types informations of a tonic-wrapped handler reported by _tonic_ to document the operation in the specification.
+
+The handlers wrapped with _tonic_ must follow the following signature.
-The handlers wrapped with *tonic* must follow the following signature.
```go
func(*gin.Context, [input object ptr]) ([output object], error)
```
+
Input and output objects are both optional, as such, the minimal accepted signature is:
+
```go
func(*gin.Context) error
```
-To wrap a handler with *tonic*, use the `tonic.Handler` method. It takes a function that follow the above signature and a default status code and return a `gin.HandlerFunc` function that can be used when you register a route with Fizz of *Gin*.
+To wrap a handler with _tonic_, use the `tonic.Handler` method. It takes a function that follow the above signature and a default status code and return a `gin.HandlerFunc` function that can be used when you register a route with Fizz of _Gin_.
Output objects can be of any type, and will be marshalled to the desired media type.
Note that the input object **MUST always be a pointer to a struct**, or the tonic wrapping will panic at runtime.
@@ -193,7 +200,8 @@ fizz.GET("/foo", []fizz.OperationOption{
### Location tags
-*tonic* uses three struct tags to recognize the parameters it should bind to the input object of your tonic-wrapped handlers:
+_tonic_ uses three struct tags to recognize the parameters it should bind to the input object of your tonic-wrapped handlers:
+
- `path`: bind from the request path
- `query`: bind from the request query string
- `header`: bind from the request headers
@@ -201,6 +209,7 @@ fizz.GET("/foo", []fizz.OperationOption{
The fields that doesn't use one of these tags will be considered as part of the request body.
The value of each struct tag represents the name of the field in each location, with options.
+
```go
type MyHandlerParams struct {
ID int64 `path:"id"`
@@ -209,30 +218,31 @@ type MyHandlerParams struct {
}
```
-*tonic* will automatically convert the value extracted from the location described by the tag to the appropriate type before binding.
+_tonic_ will automatically convert the value extracted from the location described by the tag to the appropriate type before binding.
**NOTE**: A path parameter is always required and will appear required in the spec regardless of the `validate` tag content.
### Additional tags
-You can use additional tags. Some will be interpreted by *tonic*, others will be exclusively used to enrich the *OpenAPI* specification.
+You can use additional tags. Some will be interpreted by _tonic_, others will be exclusively used to enrich the _OpenAPI_ specification.
| name | description |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `default` | *tonic* will bind this value if none was passed with the request. This should not be used if a field is also required. Read the [documentation](https://swagger.io/docs/specification/describing-parameters/) (section _Common Mistakes_) for more informations about this behaviour. |
+| `default` | _tonic_ will bind this value if none was passed with the request. This should not be used if a field is also required. Read the [documentation](https://swagger.io/docs/specification/describing-parameters/) (section _Common Mistakes_) for more informations about this behaviour. |
| `description` | Add a description of the field in the spec. |
| `deprecated` | Indicates if the field is deprecated. Accepted values are `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`. Invalid value are considered to be false. |
| `enum` | A coma separated list of acceptable values for the parameter. |
| `example` | An example value to be used in OpenAPI specification. See [section below](#Providing-Examples-for-Custom-Types) for the demonstration on how to provide example for custom types. |
| `format` | Override the format of the field in the specification. Read the [documentation](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#dataTypeFormat) for more informations. |
| `validate` | Field validation rules. Read the [documentation](https://godoc.org/gopkg.in/go-playground/validator.v8) for more informations. |
-| `explode` | Specifies whether arrays should generate separate parameters for each array item or object property (limited to query parameters with *form* style). Accepted values are `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`. Invalid value are considered to be false. |
+| `explode` | Specifies whether arrays should generate separate parameters for each array item or object property (limited to query parameters with _form_ style). Accepted values are `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`. Invalid value are considered to be false. |
### JSON/XML
-The JSON/XML encoders usually omit a field that has the tag `"-"`. This behaviour is reproduced by the *OpenAPI* generator ; a field with this tag won't appear in the properties of the schema.
+The JSON/XML encoders usually omit a field that has the tag `"-"`. This behaviour is reproduced by the _OpenAPI_ generator ; a field with this tag won't appear in the properties of the schema.
In the following example, the field `Input` is used only for binding request body parameters and won't appear in the output encoding while `Output` will be marshaled but will not be used for parameters binding.
+
```go
type Model struct {
Input string `json:"-"`
@@ -242,18 +252,20 @@ type Model struct {
### Request body
-If you want to make a request body field mandatory, you can use the tag `validate:"required"`. The validator used by *tonic* will ensure that the field is present.
+If you want to make a request body field mandatory, you can use the tag `validate:"required"`. The validator used by _tonic_ will ensure that the field is present.
To be able to make a difference between a missing value and the zero value of a type, use a pointer.
To explicitly ignore a parameter from the request body, use the tag `binding:"-"`.
-Note that the *OpenAPI* generator will ignore request body parameters for the routes with a method that is one of `GET`, `DELETE` or `HEAD`.
- > GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics as per [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3).
- [*source*](https://swagger.io/docs/specification/describing-request-body/)
+Note that the _OpenAPI_ generator will ignore request body parameters for the routes with a method that is one of `GET`, `DELETE` or `HEAD`.
+
+> GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics as per [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3).
+
+ [*source*](https://swagger.io/docs/specification/describing-request-body/)
### Schema validation
-The *OpenAPI* generator recognize some tags of the [go-playground/validator.v8](https://gopkg.in/go-playground/validator.v8) package and translate those to the [properties of the schema](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#properties) that are taken from the [JSON Schema definition](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6).
+The _OpenAPI_ generator recognize some tags of the [go-playground/validator.v8](https://gopkg.in/go-playground/validator.v8) package and translate those to the [properties of the schema](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#properties) that are taken from the [JSON Schema definition](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6).
The supported tags are: [len](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Length), [max](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Maximum), [min](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Mininum), [eq](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Equals), [gt](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Greater_Than), [gte](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Greater_Than_or_Equal), [lt](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Less_Than), [lte](https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Less_Than_or_Equal).
@@ -274,6 +286,7 @@ infos := &openapi.Info{
}
f.GET("/openapi.json", nil, f.OpenAPI(infos, "json"))
```
+
**NOTE**: The generator will never panic. However, it is strongly recommended to call `fizz.Errors` to retrieve and handle the errors that may have occured during the generation of the specification before starting your API.
#### Servers information
@@ -324,6 +337,7 @@ The names of the components can be customized in two different ways.
##### Global override
Override the name of a type globally before registering your handlers. This has the highest precedence.
+
```go
f := fizz.New()
f.Generator().OverrideTypeName(reflect.TypeOf(T{}), "OverridedName")
@@ -332,9 +346,11 @@ f.Generator().OverrideTypeName(reflect.TypeOf(T{}), "OverridedName")
##### Interface
Implements the `openapi.Typer` interface on your types.
+
```go
func (*T) TypeName() string { return "OverridedName" }
```
+
**WARNING:** You **MUST** not rely on the method receiver to return the name, because the method will be called on a new instance created by the generator with the `reflect` package.
#### Custom schemas
@@ -343,6 +359,7 @@ The spec generator creates OpenAPI schemas for your types based on their [reflec
If you want to control the output schema of a type manually, you can implement the `DataType` interface for this type.
For example, given a UUID version 4 type, declared as a struct, that should appear as a string with a custom format.
+
```go
type UUIDv4 struct { ... }
@@ -351,10 +368,11 @@ func (*UUIDv4) Type() string { return "string" }
```
The schema of the type will look like the following instead of describing all the fields of the struct.
+
```json
{
- "type": "string",
- "format": "uuid"
+ "type": "string",
+ "format": "uuid"
}
```
@@ -371,6 +389,7 @@ func (NullString) Nullable() bool { return true }
**WARNING:** You **MUST** not rely on the method receivers to return the type and format, because these methods will be called on a new instance created by the generator with the `reflect` package.
You can also override manually the type and format using `OverrideDataType()`. This has the highest precedence.
+
```go
fizz.Generator().OverrideDataType(reflect.TypeOf(&UUIDv4{}), "string", "uuid")
```
@@ -379,23 +398,26 @@ fizz.Generator().OverrideDataType(reflect.TypeOf(&UUIDv4{}), "string", "uuid")
Fizz supports some native and imported types. A schema with a proper type and format will be generated automatically, removing the need for creating your own custom schema.
-* [`time.Time`](https://golang.org/pkg/time/#Time)
-* [`time.Duration`](https://golang.org/pkg/time/#Duration)
-* [`net.URL`](https://golang.org/pkg/net/url/#URL)
-* [`net.IP`](https://golang.org/pkg/net/#IP)
+- [`time.Time`](https://golang.org/pkg/time/#Time)
+- [`time.Duration`](https://golang.org/pkg/time/#Duration)
+- [`net.URL`](https://golang.org/pkg/net/url/#URL)
+- [`net.IP`](https://golang.org/pkg/net/#IP)
Note that, according to the doc, the inherent version of the address is a semantic property, and thus cannot be determined by Fizz. Therefore, the format returned is simply `ip`. If you want to specify the version, you can use the tags `format:"ipv4"` or `format:"ipv6"`.
-* [`uuid.UUID`](https://godoc.org/github.com/gofrs/uuid#UUID)
+
+- [`uuid.UUID`](https://godoc.org/github.com/gofrs/uuid#UUID)
#### Markdown
> Throughout the specification description fields are noted as supporting CommonMark markdown formatting. Where OpenAPI tooling renders rich text it MUST support, at a minimum, markdown syntax as described by CommonMark 0.27. Tooling MAY choose to ignore some CommonMark features to address security concerns.
-[*source*](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#rich-text-formatting)
+> [_source_](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#rich-text-formatting)
To help you write markdown descriptions in Go, a simple builder is available in the sub-package `markdown`. This is quite handy to avoid conflicts with backticks that are both used in Go for litteral multi-lines strings and code blocks in markdown.
#### Providing Examples for Custom Types
+
To be able to provide examples for custom types, they must implement the `json.Marshaler` and/or `yaml.Marshaler` and the following interface:
+
```go
type Exampler interface {
ParseExample(v string) (interface{}, error)
@@ -406,30 +428,32 @@ If the custom type implements the interface, Fizz will pass the value from the `
## Known limitations
-- Since *OpenAPI* is based on the *JSON Schema* specification itself, objects (Go maps) with keys that are not of type `string` are not supported and will be ignored during the generation of the specification.
+- Since _OpenAPI_ is based on the _JSON Schema_ specification itself, objects (Go maps) with keys that are not of type `string` are not supported and will be ignored during the generation of the specification.
- Recursive embedding of the same type is not supported, at any level of recursion. The generator will warn and skip the offending fields.
- ```go
- type A struct {
- Foo int
- *A // ko, embedded and same type as parent
- A *A // ok, not embedded
- *B // ok, different type
- }
-
- type B struct {
- Bar string
- *A // ko, type B is embedded in type A
- *C // ok, type C does not contains an embedded field of type A
- }
-
- type C struct {
- Baz bool
- }
- ```
+
+ ```go
+ type A struct {
+ Foo int
+ *A // ko, embedded and same type as parent
+ A *A // ok, not embedded
+ *B // ok, different type
+ }
+
+ type B struct {
+ Bar string
+ *A // ko, type B is embedded in type A
+ *C // ok, type C does not contains an embedded field of type A
+ }
+
+ type C struct {
+ Baz bool
+ }
+ ```
## Examples
A simple runnable API is available in `examples/market`.
+
```shell
go build
./market
diff --git a/examples/market/router.go b/examples/market/router.go
index 729f832..80a7436 100644
--- a/examples/market/router.go
+++ b/examples/market/router.go
@@ -3,12 +3,11 @@ package main
import (
"fmt"
+ "github.com/demand-iq/fizz"
+ "github.com/demand-iq/fizz/openapi"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/loopfz/gadgeto/tonic"
-
- "github.com/wI2L/fizz"
- "github.com/wI2L/fizz/openapi"
)
// NewRouter returns a new router for the
diff --git a/fizz.go b/fizz.go
index 7339898..577d182 100644
--- a/fizz.go
+++ b/fizz.go
@@ -11,9 +11,9 @@ import (
"strings"
"time"
+ "github.com/demand-iq/fizz/openapi"
"github.com/gin-gonic/gin"
"github.com/loopfz/gadgeto/tonic"
- "github.com/wI2L/fizz/openapi"
)
const ctxOpenAPIOperation = "_ctx_openapi_operation"
diff --git a/fizz_test.go b/fizz_test.go
index c5fd7af..e989047 100644
--- a/fizz_test.go
+++ b/fizz_test.go
@@ -19,7 +19,7 @@ import (
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v2"
- "github.com/wI2L/fizz/openapi"
+ "github.com/demand-iq/fizz/openapi"
)
func TestMain(m *testing.M) {
diff --git a/go.mod b/go.mod
index b789021..cdf8d67 100644
--- a/go.mod
+++ b/go.mod
@@ -1,28 +1,38 @@
-module github.com/wI2L/fizz
+module github.com/demand-iq/fizz
-go 1.12
+go 1.18
require (
github.com/Pallinder/go-randomdata v1.2.0
github.com/gin-contrib/cors v1.3.0
github.com/gin-gonic/gin v1.7.7
- github.com/go-playground/validator/v10 v10.9.0 // indirect
github.com/gofrs/uuid v3.2.0+incompatible
+ github.com/juju/errors v1.0.0
+ github.com/loopfz/gadgeto v0.9.0
+ github.com/stretchr/testify v1.7.0
+ golang.org/x/text v0.4.0
+ gopkg.in/yaml.v2 v2.4.0
+)
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/go-playground/locales v0.14.0 // indirect
+ github.com/go-playground/universal-translator v0.18.0 // indirect
+ github.com/go-playground/validator/v10 v10.9.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.1.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
- github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9
- github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
- github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 // indirect
- github.com/loopfz/gadgeto v0.9.0
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
- github.com/stretchr/testify v1.7.0
- github.com/ugorji/go v1.2.6 // indirect
- golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
- golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
- golang.org/x/text v0.3.7
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/ugorji/go/codec v1.2.6 // indirect
+ golang.org/x/crypto v0.3.0 // indirect
+ golang.org/x/sys v0.2.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/go-playground/validator.v9 v9.30.0 // indirect
- gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
- gopkg.in/yaml.v2 v2.4.0
+ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
diff --git a/go.sum b/go.sum
index 79770f2..20926eb 100644
--- a/go.sum
+++ b/go.sum
@@ -45,16 +45,13 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
-github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9 h1:hJix6idebFclqlfZCHE7EUX7uqLCyb70nHNHH1XKGBg=
-github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
-github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
-github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
-github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 h1:Pp8RxiF4rSoXP9SED26WCfNB28/dwTDpPXS8XMJR8rc=
-github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
+github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM=
+github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -81,8 +78,9 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -92,7 +90,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v0.0.0-20190128213124-ee1426cffec0/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
@@ -101,31 +98,29 @@ github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxW
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
+golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -144,8 +139,6 @@ gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/R
gopkg.in/go-playground/validator.v9 v9.26.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.30.0 h1:Wk0Z37oBmKj9/n+tPyBHZmeL19LaCoK3Qq48VwYENss=
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
-gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
-gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
diff --git a/markdown/README.md b/markdown/README.md
index a858756..0514a9f 100644
--- a/markdown/README.md
+++ b/markdown/README.md
@@ -1,14 +1,13 @@
-Markdown Builder
-================
+# Markdown Builder
-[](https://godoc.org/github.com/wI2L/fizz/markdown)
+[](https://godoc.org/ github.com/demand-iq/fizz/markdown)
This is a simple builder to help you create **Mardown** content in Go.
## Usage
```go
-import "github.com/wI2L/fizz/markdown"
+import " github.com/demand-iq/fizz/markdown"
builder := markdown.Builder{}
@@ -16,7 +15,7 @@ builder.
H1("Markdown Builder").
P("A simple builder to help your write Markdown in Go").
H2("Installation").
- Code("go get -u github.com/wI2L/fizz", "bash").
+ Code("go get -u github.com/demand-iq/fizz", "bash").
H2("Todos").
BulletedList(
"write tests",
@@ -36,7 +35,7 @@ md := builder.String()
----------------------------------
```bash
- go get -u github.com/wI2L/fizz", "bash
+ go get -u github.com/demand-iq/fizz", "bash
```
Todos
@@ -53,32 +52,32 @@ The builder have two kinds of elements, block and inline elements. Block element
### Inline
-* Alternative titles ⇒ `builder.AltH1` and `builder.AltH2`
-* Emphasis ⇒ `builder.Emphasis` and `builder.Italic`
-* Strong emphasis ⇒ `builder.StrongEmphasis` and `builder.Bold`
-* Combined emphasis ⇒ `builder.StrongEmphasis`
-* Strikethrough ⇒ `builder.Strikethrough`
-* Code ⇒ `builder.InlineCode`
-* Link ⇒ `builder.Link`
-* Image ⇒ `builder.Image`
+- Alternative titles ⇒ `builder.AltH1` and `builder.AltH2`
+- Emphasis ⇒ `builder.Emphasis` and `builder.Italic`
+- Strong emphasis ⇒ `builder.StrongEmphasis` and `builder.Bold`
+- Combined emphasis ⇒ `builder.StrongEmphasis`
+- Strikethrough ⇒ `builder.Strikethrough`
+- Code ⇒ `builder.InlineCode`
+- Link ⇒ `builder.Link`
+- Image ⇒ `builder.Image`
### Block
-* Headers ⇒ `builder.H1`, `builder.H2`, `builder.H3`, `builder.H4`, `builder.H5`, `builder.H6`
-* Paragraph ⇒ `builder.P`
-* Line ⇒ `builder.Line`
+- Headers ⇒ `builder.H1`, `builder.H2`, `builder.H3`, `builder.H4`, `builder.H5`, `builder.H6`
+- Paragraph ⇒ `builder.P`
+- Line ⇒ `builder.Line`
A line is similar to a paragraph but it doesn't insert a line break at the end.
-* Line break ⇒ `builder.BR`
-* Blockquote ⇒ `builder.Blockquote`
-* Horizontal rule ⇒ `builder.HR`
-* Code ⇒ `builder.Code`
-* Lists
+- Line break ⇒ `builder.BR`
+- Blockquote ⇒ `builder.Blockquote`
+- Horizontal rule ⇒ `builder.HR`
+- Code ⇒ `builder.Code`
+- Lists
1. Bulleted ⇒ `builder.BulletedList`
2. Numbered ⇒ `builder.NumberedList`
### Github Flavor
-The builder also support the tables extension of the *GitHub Flavored Markdown Spec*.
+The builder also support the tables extension of the _GitHub Flavored Markdown Spec_.
```go
builder.Table(
@@ -95,6 +94,7 @@ builder.Table(
}
)
```
+
```
| Letter | Title | ID |
| :----: | :-------------------: | ------: |
diff --git a/openapi/generator.go b/openapi/generator.go
index 99f6833..2be3a47 100644
--- a/openapi/generator.go
+++ b/openapi/generator.go
@@ -28,6 +28,10 @@ var (
ginPathParamRe = regexp.MustCompile(`\/:([^\/]*)`)
)
+var (
+ typePathRe = regexp.MustCompile(`([\*\-a-zA-Z0-9\.\/_]+)(\[([\*\-a-zA-Z0-9\.\/_]+)\])?`)
+)
+
// mediaTags maps media types to well-known
// struct tags used for marshaling.
var mediaTags = map[string]string{
@@ -1149,7 +1153,14 @@ func (g *Generator) typeName(t reflect.Type) string {
return tn.TypeName()
}
}
- name := t.String() // package.name.
+ rawName := t.String() // package.name.
+ submatch := typePathRe.FindStringSubmatch(rawName)
+ var name, typeParam = submatch[1], submatch[3]
+ if len(typeParam) > 0 {
+ lastIndex := strings.LastIndex(typeParam, "/")
+ typeParam = "-" + typeParam[lastIndex+1:]
+ }
+
sp := strings.Index(name, ".")
pkg := name[:sp]
@@ -1161,9 +1172,9 @@ func (g *Generator) typeName(t reflect.Type) string {
typ := name[sp+1:]
if !g.fullNames {
- return strings.Title(typ)
+ return strings.Title(typ) + typeParam
}
- return strings.Title(pkg) + strings.Title(typ)
+ return strings.Title(pkg) + strings.Title(typ) + typeParam
}
// updateSchemaValidation fills the fields of the schema
@@ -1255,7 +1266,7 @@ func fieldNameFromTag(sf reflect.StructField, tagName string) string {
return name
}
-/// parseExampleValue is used to transform the string representation of the example value to the correct type.
+// / parseExampleValue is used to transform the string representation of the example value to the correct type.
func parseExampleValue(t reflect.Type, value string) (interface{}, error) {
// If the type implements Exampler use the ParseExample method to create the example
i, ok := reflect.New(t).Interface().(Exampler)
diff --git a/openapi/generator_test.go b/openapi/generator_test.go
index e63ac74..1b241cf 100644
--- a/openapi/generator_test.go
+++ b/openapi/generator_test.go
@@ -74,6 +74,8 @@ type (
V struct {
L int
}
+ Foo[T any] struct {
+ }
)
func (*X) TypeName() string { return "XXX" }
@@ -601,6 +603,8 @@ func TestTypeName(t *testing.T) {
// Unnamed type.
assert.Equal(t, "", g.typeName(rt(struct{}{})))
+ // generic type
+ assert.Equal(t, "Foo-openapi.X", g.typeName(rt(Foo[X]{})))
}
// TestSetInfo tests that the informations