|
1 |
| -# openapi |
| 1 | +# openapi - an OpenAPI 3.x library for Go |
2 | 2 |
|
3 |
| -Package openapi is a set of Go types for [OpenAPI Specification |
4 |
| -3.1](https://spec.openapis.org/oas/v3.1.0). The primary purpose of the package |
5 |
| -is to assist in generation of OpenAPI documentation or to offer building blocks |
6 |
| -for code-generation. |
| 3 | +openapi is a library for for OpenAPI 3.x ([3.1](https://spec.openapis.org/oas/v3.1.0), |
| 4 | +[3.0](https://spec.openapis.org/oas/v3.0.3)). |
7 | 5 |
|
8 |
| -## Documentation |
| 6 | +The primary purpose of the package is to offer building blocks for code and |
| 7 | +documentation generation. |
9 | 8 |
|
10 |
| -[Documentation can be found on pkg.go.dev](https://pkg.go.dev/github.com/chanced/openapi). |
| 9 | +:warning: This library is in an alpha state; expect breaking changes and bugs. |
| 10 | + |
| 11 | +## Features |
| 12 | + |
| 13 | +- `$ref` resolution |
| 14 | +- All keys retain their order from the markup using slices of key/values which |
| 15 | + aids with code generation. |
| 16 | +- Validation ([see the validation seciton](#validation)) |
| 17 | +- All non-primitive nodes have an absolute & relative location |
| 18 | +- Strings are [text.Text](https://github.com/chanced/caps) which has case |
| 19 | + conversions and `strings` functions as methods. |
| 20 | +- Extensions, unknown JSON Schema keywords, examples, and a few other fields |
| 21 | + are instances of [jsonx.RawMessage](https://github.com/chanced/jsonx) which |
| 22 | + comes with a few helper methods. |
| 23 | +- Supports both JSON and YAML |
| 24 | + |
| 25 | +## Issues |
| 26 | + |
| 27 | +- **Testing.** The code coverage is abysmal at the moment. As I find time, I'll add coverage. |
| 28 | +- **`$dynamicRef` / `$dynamicAnchor`** is not really supported. While the |
| 29 | + references are loaded, the dynamic overriding is not. I simply have no idea |
| 30 | + how to solve it. If you have ideas, I'd really like to hear them. |
| 31 | +- **Validation.** [See the Validation section](#validation). |
| 32 | +- **Errors.** Errors and error messages need a lot of work. |
| 33 | +- [jsonpointer](https://github.com/chanced/jsonpointer)'s Resolve, Assign, and |
| 34 | + Delete do not currently work. I need to update the jsonpointer library |
| 35 | + before its interfaces can be implemented for types within this library. |
| 36 | +- Values of `$anchor` and `$dynamicAnchor` must be unique to a file. |
| 37 | + Conditional `$dynamicAnchor` `$recursiveAnchor` are going to be challenging. |
| 38 | + See below. |
| 39 | +- `$dynamicRef` and `$recursiveRef` are incredibly tricky with respect to |
| 40 | + static analysis, which is what this library was built for. You should avoid |
| 41 | + conditional branches with `$dynamicAnchor`s within the same file. If you |
| 42 | + need a conditional dynamics, move the branch into its own file and have the |
| 43 | + conditional statement reference the branch. |
| 44 | + |
| 45 | +## Usage |
| 46 | + |
| 47 | +```go |
| 48 | +package main |
| 49 | + |
| 50 | +import ( |
| 51 | + "github.com/chanced/openapi" |
| 52 | + "github.com/chanced/uri" |
| 53 | + "github.com/santhosh-tekuri/jsonschema/v5" |
| 54 | + "embed" |
| 55 | + "io" |
| 56 | + "path/filepath" |
| 57 | + "log" |
| 58 | +) |
| 59 | + |
| 60 | +//go:embed spec |
| 61 | +var spec embed.FS |
| 62 | + |
| 63 | +func main() { |
| 64 | + ctx := context.Background() |
| 65 | + |
| 66 | + c, err := openapi.SetupCompiler(jsonschema.NewCompiler()) // adding schema files |
| 67 | + if err != nil { |
| 68 | + log.Fatal(err) |
| 69 | + } |
| 70 | + v, err := openapi.NewValidator(c) |
| 71 | + if err != nil { |
| 72 | + log.Fatal(err) |
| 73 | + } |
| 74 | + |
| 75 | + fn := func(_ context.Context, uri uri.URI, kind openapi.Kind) (openapi.Kind, []byte, error){ |
| 76 | + f, err := schema.Open(fp) |
| 77 | + if err != nil { |
| 78 | + log.Fatal(err) |
| 79 | + } |
| 80 | + // you can return either JSON or YAML |
| 81 | + d, err := io.ReadAll(f) |
| 82 | + if err != nil{ |
| 83 | + log.fatal(err) |
| 84 | + } |
| 85 | + // use the uri or the data to determine the Kind |
| 86 | + return openapi.KindDocument, d, nil |
| 87 | + } |
| 88 | + // you can Load either JSON or YAML |
| 89 | + // Load validates the Document as well. |
| 90 | + doc, err := openapi.Load(ctx, "spec/openapi.yaml", v, fn) |
| 91 | + if err != nil{ |
| 92 | + log.Fatal(err) |
| 93 | + } |
| 94 | + _ = doc // *openapi.Document |
| 95 | +} |
| 96 | +``` |
11 | 97 |
|
12 | 98 | ## Validation
|
13 | 99 |
|
14 |
| -Currently, specifications are validated with JSON Schema. Per OpenAPI's |
15 |
| -documentation, this may not be enough to properly encapsulate all the nuances |
16 |
| -of a specification. However, JSON Schema is able to properly validate the current |
17 |
| -OpenAPI 3.1 Specification test suite. |
| 100 | +The standard validator (`StdValidator`) currently validates OpenAPI documents |
| 101 | +with JSON Schema. Per OpenAPI's documentation, this may not be enough to |
| 102 | +properly encapsulate all the nuances of a specification. However, JSON Schema is |
| 103 | +able to successfully validate the current OpenAPI 3.1 Specification test suite. |
| 104 | + |
| 105 | +Validation something that needs work. If you have an edge case that is not |
| 106 | +covered, you can implement your own Validator either by wrapping `StdValidator` |
| 107 | +or simply creating your own. |
| 108 | + |
| 109 | +If you do find cases where the current validator is not sufficient, please open |
| 110 | +an issue so that the library can be updated with proper coverage in the future. |
| 111 | + |
| 112 | +Regarding JSON Schema, as of writing this, the only library able to support JSON |
| 113 | +Schema 2020-12 is |
| 114 | +[github.com/santhosh-tekuri/jsonschema](https://github.com/santhosh-tekuri/jsonschema) |
| 115 | +and so the `Compiler`'s interface was modeled after its API. If you would like |
| 116 | +to use a different implementation of JSON Schema with the `StdValidator` the |
| 117 | +interfaces you need to write an adapter for are: |
| 118 | + |
| 119 | +```go |
| 120 | +type Compiler interface { |
| 121 | + AddResource(id string, r io.Reader) error |
| 122 | + Compile(url string) (CompiledSchema, error) |
| 123 | +} |
18 | 124 |
|
19 |
| -Please open an issue if you run into an edge case that is not validated adequately. |
| 125 | +type CompiledSchema interface { |
| 126 | + Validate(data interface{}) error |
| 127 | +} |
| 128 | +``` |
20 | 129 |
|
21 | 130 | ## Contributions
|
22 | 131 |
|
23 |
| -Please feel free to open up an issue or create a pull request if there are features |
24 |
| -you'd like to contribute or issues. |
25 |
| - |
26 |
| -## Dependencies |
27 |
| - |
28 |
| -- [github.com/santhosh-tekuri/jsonschema/v5](https://github.com/santhosh-tekuri/jsonschema/v5) (used for json schema validation) |
29 |
| -- [github.com/evanphx/json-patch/v5](https://github.com/evanphx/json-patch/v5) (used for testing purposes) |
30 |
| -- [github.com/stretchr/testify](https://github.com/stretchr/testify) (testing) |
31 |
| -- [github.com/tidwall/gjson](https://github.com/tidwall/gjson) (json parsing) |
32 |
| -- [github.com/tidwall/sjson](https://github.com/tidwall/sjson) (json manipulation) |
33 |
| -- [github.com/wI2L/jsondiff](https://github.com/wI2L/jsondiff) (testing purposes) |
34 |
| -- [gopkg.in/yaml.v2](https://github.com/wI2L/jsondiff) (yaml) |
35 |
| -- [sigs.k8s.io/yaml](https://sigs.k8s.io/yaml) (yaml) |
36 |
| -- [github.com/chanced/cmpjson](https://github.com/chanced/cmpjson) (testing purposes) |
37 |
| -- [github.com/chanced/dynamic](https://github.com/chanced/dynamic) (json parsing) |
38 |
| -- [github.com/pkg/errors](https://github.com/pkg/errors) (errors) |
| 132 | +Please feel free to open up an issue or create a pull request if you find issues |
| 133 | +or if there are features you'd like to see added. |
39 | 134 |
|
40 | 135 | ## License
|
41 | 136 |
|
|
0 commit comments