{"id":13872320,"url":"https://github.com/mattpolzin/OpenAPIKit","last_synced_at":"2025-07-16T02:30:31.394Z","repository":{"id":43682274,"uuid":"193250002","full_name":"mattpolzin/OpenAPIKit","owner":"mattpolzin","description":"Codable Swift OpenAPI implementation.","archived":false,"fork":false,"pushed_at":"2024-11-01T22:44:54.000Z","size":33025,"stargazers_count":286,"open_issues_count":14,"forks_count":37,"subscribers_count":8,"default_branch":"main","last_synced_at":"2024-11-21T09:03:19.685Z","etag":null,"topics":["openapi"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mattpolzin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-22T15:35:36.000Z","updated_at":"2024-11-17T19:38:36.000Z","dependencies_parsed_at":"2024-05-21T03:35:45.791Z","dependency_job_id":null,"html_url":"https://github.com/mattpolzin/OpenAPIKit","commit_stats":{"total_commits":573,"total_committers":6,"mean_commits":95.5,"dds":"0.022687609075043635","last_synced_commit":"d3c27d8fc488a97aef9a3a6a39c1b443900c866f"},"previous_names":[],"tags_count":101,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattpolzin%2FOpenAPIKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattpolzin%2FOpenAPIKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattpolzin%2FOpenAPIKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattpolzin%2FOpenAPIKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mattpolzin","download_url":"https://codeload.github.com/mattpolzin/OpenAPIKit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225700964,"owners_count":17510448,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["openapi"],"created_at":"2024-08-05T23:00:39.658Z","updated_at":"2024-11-23T20:30:52.340Z","avatar_url":"https://github.com/mattpolzin.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"[![sswg:sandbox|94x20](https://img.shields.io/badge/sswg-sandbox-lightgrey.svg)](https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level) [![Swift 5.1+](http://img.shields.io/badge/Swift-5.1+-blue.svg)](https://swift.org)\n\n[![MIT license](http://img.shields.io/badge/license-MIT-lightgrey.svg)](http://opensource.org/licenses/MIT) ![Tests](https://github.com/mattpolzin/OpenAPIKit/workflows/Tests/badge.svg)\n\n# OpenAPIKit \u003c!-- omit in toc --\u003e\n\nA library containing Swift types that encode to- and decode from [OpenAPI 3.0.x](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md) and [OpenAPI 3.1.x](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) Documents and their components.\n\nThe single most confusing thing you will grapple with out of the gate is explained by the following grid of what OpenAPIKit versions support which OpenAPI specification versions.\n\n| OpenAPIKit  | OpenAPI v3.0  | OpenAPI v3.1 |\n|-------------|---------------|--------------|\n| v2.x        | ✅            | ❌           |\n| v3.x        | ✅            | ✅           |\n\n- [Usage](#usage)\n  - [Migration](#migration)\n    - [1.x to 2.x](#1.x-to-2.x)\n    - [2.x to 3.x](#2.x-to-3.x)\n  - [Decoding OpenAPI Documents](#decoding-openapi-documents)\n    - [Decoding Errors](#decoding-errors)\n  - [Encoding OpenAPI Documents](#encoding-openapi-documents)\n  - [Validating OpenAPI Documents](#validating-openapi-documents)\n  - [Supporting OpenAPI 3.0.x Documents](#supporting-openapi-30x-documents)\n  - [A note on dictionary ordering](#a-note-on-dictionary-ordering)\n  - [OpenAPI Document structure](#openapi-document-structure)\n    - [Document Root](#document-root)\n    - [Routes](#routes)\n    - [Endpoints](#endpoints)\n    - [Request/Response Bodies](#requestresponse-bodies)\n    - [Schemas](#schemas)\n    - [JSON References](#json-references)\n    - [Security Requirements](#security-requirements)\n    - [Specification Extensions](#specification-extensions)\n  - [Dereferencing \u0026 Resolving](#dereferencing--resolving)\n- [Curated Integrations](#curated-integrations)\n  - [Declarative OpenAPI Documents](#declarative-openapi-documents)\n  - [Generating OpenAPI Documents](#generating-openapi-documents)\n  - [Semantic Diffing of OpenAPI Documents](#semantic-diffing-of-openapi-documents)\n- [Notes](#notes)\n- [Contributing](#contributing)\n- [Security](#security)\n- [Specification Coverage \u0026 Type Reference](#specification-coverage--type-reference)\n\n## Usage\n\n### Migration\n#### 1.x to 2.x\nIf you are migrating from OpenAPIKit 1.x to OpenAPIKit 2.x, check out the [v2 migration guide](./documentation/v2_migration_guide.md).\n\n#### 2.x to 3.x\nIf you are migrating from OpenAPIKit 2.x to OpenAPIKit 3.x, check out the [v3 migration guide](./documentation/v3_migration_guide.md).\n\nYou will need to start being explicit about which of the two new modules you want to use in your project: `OpenAPIKit` (now supports OpenAPI spec v3.1) and/or `OpenAPIKit30` (continues to support OpenAPI spec v3.0 like the previous versions of OpenAPIKit did).\n\nIn package manifests, dependencies will be one of:\n```\n// v3.0 of spec:\ndependencies: [.product(name: \"OpenAPIKit30\", package: \"OpenAPIKit\")]\n\n// v3.1 of spec:\ndependencies: [.product(name: \"OpenAPIKit\", package: \"OpenAPIKit\")]\n```\n\nYour imports need to be specific as well:\n```swift\n// v3.0 of spec:\nimport OpenAPIKit30\n\n// v3.1 of spec:\nimport OpenAPIKit\n```\n\nIt is recommended that you build your project against the `OpenAPIKit` module and only use `OpenAPIKit30` to support reading OpenAPI 3.0.x documents in and then [converting them](#supporting-openapi-30x-documents) to OpenAPI 3.1.x documents. The situation not supported yet by this strategy is where you need to write out an OpenAPI 3.0.x document (as opposed to 3.1.x). That is a planned feature but it has not yet been implemented. If your use-case benefits from reading in an OpenAPI 3.0.x document and also writing out an OpenAPI 3.0.x document then you can operate entirely against the `OpenAPIKit30` module.\n\n### Decoding OpenAPI Documents\n\nMost documentation will focus on what it looks like to work with the `OpenAPIKit` module and OpenAPI 3.1.x documents. If you need to support OpenAPI 3.0.x documents, take a look at the section on [supporting OpenAPI 3.0.x documents](#supporting-openapi-30x-documents) before you get too deep into this library's docs.\n\nYou can decode a JSON OpenAPI document (i.e. using the `JSONDecoder` from **Foundation** library) or a YAML OpenAPI document (i.e. using the `YAMLDecoder` from the [**Yams**](https://github.com/jpsim/Yams) library) with the following code:\n```swift\nimport OpenAPIKit\n\nlet decoder = ... // JSONDecoder() or YAMLDecoder()\nlet openAPIDoc = try decoder.decode(OpenAPI.Document.self, from: ...)\n```\n\n#### Decoding Errors\nYou can wrap any error you get back from a decoder in `OpenAPI.Error` to get a friendlier human-readable description from `localizedDescription`.\n\n```swift\ndo {\n  try decoder.decode(OpenAPI.Document.self, from: ...)\n} catch let error {\n  print(OpenAPI.Error(from: error).localizedDescription)  \n}\n```\n\n### Encoding OpenAPI Documents\n\nYou can encode a JSON OpenAPI document (i.e. using the `JSONEncoder` from the **Foundation** library) or a YAML OpenAPI document (i.e. using the `YAMLEncoder` from the [**Yams**](https://github.com/jpsim/Yams) library) with the following code:\n```swift\nlet openAPIDoc: OpenAPI.Document = ...\nlet encoder = ... // JSONEncoder() or YAMLEncoder()\nlet encodedOpenAPIDoc = try encoder.encode(openAPIDoc)\n```\n\n### Validating OpenAPI Documents\nThanks to Swift's type system, the vast majority of the OpenAPI Specification is represented by the types of OpenAPIKit -- you cannot create bad OpenAPI docuements in the first place and decoding a document will fail with generally useful errors.\n\nThat being said, there are a small number of additional checks that you can perform to really put any concerns to rest.\n\n```swift\nlet openAPIDoc: OpenAPI.Document = ...\n// perform additional validations on the document:\ntry openAPIDoc.validate()\n```\n\nYou can use this same validation system to dig arbitrarily deep into an OpenAPI Document and assert things that the OpenAPI Specification does not actually mandate. For more on validation, see the [OpenAPIKit Validation Documentation](./documentation/validation.md).\n\n### Supporting OpenAPI 3.0.x Documents\nIf you need to operate on OpenAPI 3.0.x documents and only 3.0.x documents, you can use the `OpenAPIKit30` module throughout your code.\n\nHowever, if you need to operate on both OpenAPI 3.0.x and 3.1.x documents, the recommendation is to use the OpenAPIKit compatibility layer to read in a 3.0.x document and convert it to a 3.1.x document so that you can use just the one set of Swift types throughout most of your program. An example of that follows.\n\nIn this example, only one file in the whole project needs to import `OpenAPIKit30` or `OpenAPIKitCompat`. Every other file would just import `OpenAPIKit` and work with the document in the 3.1.x format.\n\n#### Converting from 3.0.x to 3.1.x\n```swift\n// import OpenAPIKit30 for OpenAPI 3.0 document support\nimport OpenAPIKit30\n// import OpenAPIKit for OpenAPI 3.1 document support\nimport OpenAPIKit\n// import OpenAPIKitCompat to convert between the versions\nimport OpenAPIKitCompat\n\n// if most of your project just works with OpenAPI v3.1, most files only need to import OpenAPIKit.\n// Only in the file where you are supporting converting from OpenAPI v3.0 to v3.1 do you need the\n// other two imports.\n\n// we can support either version by attempting to parse an old version and then a new version if the old version fails\nlet oldDoc: OpenAPIKit30.OpenAPI.Document?\nlet newDoc: OpenAPIKit.OpenAPI.Document\n\noldDoc = try? JSONDecoder().decode(OpenAPI.Document.self, from: someFileData)\n\nnewDoc = oldDoc?.convert(to: .v3_1_0) ??\n  (try! JSONDecoder().decode(OpenAPI.Document.self, from: someFileData))\n// ^ Here we simply fall-back to 3.1.x if loading as 3.0.x failed. You could do a more\n//   graceful job of this by determining up front which version to attempt to load or by \n//   holding onto errors for each decode attempt so you can tell the user why the document \n//   failed to decode as neither 3.0.x nor 3.1.x if it fails in both cases.\n```\n\n### A note on dictionary ordering\nThe **Foundation** library's `JSONEncoder` and `JSONDecoder` do not make any guarantees about the ordering of keyed containers. This means decoding a JSON OpenAPI Document and then encoding again might result in the document's various hashed structures being in a different order.\n\nIf retaining order is important for your use-case, I recommend the [**Yams**](https://github.com/jpsim/Yams) and [**FineJSON**](https://github.com/omochi/FineJSON) libraries for YAML and JSON respectively. Also keep in mind that JSON is entirely valid YAML and therefore you will likely get good results from Yams decoding of JSON as well (it just won't _encode_ as valid JSON). \n\nThe Foundation JSON encoding and decoding will be the most stable and battle-tested option with Yams as a pretty well established and stable option as well. FineJSON is lesser used (to my knowledge) but I have had success with it in the past.\n\n### OpenAPI Document structure\nThe types used by this library largely mirror the object definitions found in the OpenAPI specification [version 3.1.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) (`OpenAPIKit` module) and [version 3.0.3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md) (`OpenAPIKit30` module). The [Project Status](#project-status) lists each object defined by the spec and the name of the respective type in this library. The project status page currently focuses on OpenAPI 3.1.x but for the purposes of determining what things are named and what is supported you can mostly infer the status of the OpenAPI 3.0.x support as well.\n\n#### Document Root\nAt the root there is an `OpenAPI.Document`. In addition to some information that applies to the entire API, the document contains `OpenAPI.Components` (essentially a dictionary of reusable components that can be referenced with `JSONReferences` and `OpenAPI.References`) and an `OpenAPI.PathItem.Map` (a dictionary of routes your API defines).\n\n#### Routes\nEach route is an entry in the document's `OpenAPI.PathItem.Map`. The keys of this dictionary are the paths for each route (i.e. `/widgets`). The values of this dictionary are `OpenAPI.PathItems` which define any combination of endpoints (i.e. `GET`, `POST`, `PATCH`, etc.) that the given route supports. In addition to accessing endpoints on a path item under the name of the method (`.get`, `.post`, etc.), you can get an array of pairs matching endpoint methods to operations with the `.endpoints` method on `PathItem`.\n\n#### Endpoints\nEach endpoint on a route is defined by an `OpenAPI.Operation`. Among other things, this operation can specify the parameters (path, query, header, etc.), request body, and response bodies/codes supported by the given endpoint.\n\n#### Request/Response Bodies\nRequest and response bodies can be defined in great detail using OpenAPI's derivative of the JSON Schema specification. This library uses the `JSONSchema` type for such schema definitions.\n\n#### Schemas\n**Fundamental types** are specified as `JSONSchema.integer`, `JSONSchema.string`, `JSONSchema.boolean`, etc.\n\n**Schema attributes** are given as arguments to static constructors. By default, schemas are **non-nullable**, **required**, and **generic**. The below examples are not comprehensive and you can pass any number of the optional attributes to the static constructors as arguments.\n\nA schema can be made **optional** (i.e. it can be omitted) with `JSONSchema.integer(required: false)` or an existing schema can be asked for an `optionalSchemaObject()`. \n\nA schema can be made **nullable** with `JSONSchema.number(nullable: true)` or an existing schema can be asked for a `nullableSchemaObject()`.\n\nNullability highlights an important decision OpenAPIKit makes. The JSON Schema specification that dictates how OpenAPI v3.1 documents _encode_ nullability states that a nullable property is encoded as having the `null` type in addition to whatever other type(s) it has. So in OpenAPIKit you set `nullability` as a property of a schema, but when encoded/decoded it will represent the inclusion of absence of `null` in the list of `type`s of the schema. If you are using the `OpenAPIKit30` module then nullability is encoded as a `nullable` property per the OpenAPI 3.0.x specification.\n\nSome types of schemas can be further specialized with a **format**. For example, `JSONSchema.number(format: .double)` or `JSONSchema.string(format: .dateTime)`.\n\nYou can specify a schema's **allowed values** (e.g. for an enumerated type) with `JSONSchema.string(allowedValues: \"hello\", \"world\")`.\n\nEach type of schema has its own additional set of properties that can be specified. For example, integers can have a **minimum value**: `JSONSchema.integer(minimum: (0, exclusive: true))`. `exclusive: true` in this context means the number must be strictly greater than 0 whereas `exclusive: false` means the number must be greater-than or equal-to 0.\n\nCompound objects can be built with `JSONSchema.array`, `JSONSchema.object`, `JSONSchema.all(of:)`, etc.\n\nFor example, perhaps a person is represented by the schema:\n```swift\nJSONSchema.object(\n  title: \"Person\",\n  properties: [\n    \"first_name\": .string(minLength: 2),\n    \"last_name\": .string(nullable: true),\n    \"age\": .integer,\n    \"favorite_color\": .string(allowedValues: \"red\", \"green\", \"blue\")\n  ]\n)\n```\n\nTake a look at the [OpenAPIKit Schema Object](./documentation/schema_object.md) documentation for more information.\n\n#### OpenAPI References\nThe `OpenAPI.Reference` type represents the OpenAPI specification's reference support that is essentially just JSON Reference specification compliant but with the ability to override summaries and descriptions at the reference site where appropriate.\n\nFor details on the underlying reference support, see the next section on the `JSONReference` type.\n\n#### JSON References\nThe `JSONReference` type allows you to work with OpenAPIDocuments that store some of their information in the shared Components Object dictionary or even external files. Only documents where all references point to the Components Object can be dereferenced currently, but you can encode and decode all references.\n\nYou can create an external reference with `JSONReference.external(URL)`. Internal references usually refer to an object in the Components Object dictionary and are constructed with `JSONReference.component(named:)`. If you need to refer to something in the current file but not in the Components Object, you can use `JSONReference.internal(path:)`.\n\nYou can check whether a given `JSONReference` exists in the Components Object with `document.components.contains()`. You can access a referenced object in the Components Object with `document.components[reference]`.\n\nYou can create references from the Components Object with `document.components.reference(named:ofType:)`. This method will throw an error if the given component does not exist in the ComponentsObject.\n\nYou can use `document.components.lookup()` or the `Components` type's `subscript` to turn an `Either` containing either a reference or a component into an optional value of that component's type (having either pulled it out of the `Either` or looked it up in the Components Object). The `lookup()` method throws when it can't find an item whereas `subscript` returns `nil`.\n\nFor example,\n```swift\nlet apiDoc: OpenAPI.Document = ...\nlet addBooksPath = apiDoc.paths[\"/cloudloading/addBook\"]\n\nlet addBooksParameters: [OpenAPI.Parameter]? = addBooksPath?.parameters.compactMap { apiDoc.components[$0] }\n```\n\nNote that this looks a component up in the Components Object but it does not transform it into an entirely derefernced object in the same way as is described below in the [Dereferencing \u0026 Resolving](#dereferencing--resolving) section.\n\n#### Security Requirements\nIn the OpenAPI specifcation, a security requirement (like can be found on the root Document or on Operations) is a dictionary where each key is the name of a security scheme found in the Components Object and each value is an array of applicable scopes (which is of course only a non-empty array when the security scheme type is one for which \"scopes\" are relevant).\n\nOpenAPIKit defines the `SecurityRequirement` typealias as a dictionary with `JSONReference` keys; These references point to the Components Object and provide a slightly stronger contract than the String values required by the OpenAPI specification. Naturally, these are encoded to JSON/YAML as String values rather than JSON References to maintain compliance with the OpenAPI Specification.\n\nTo give an example, let's say you want to describe OAuth 2.0 authentication via the implicit flow. First, define a Security Scheme:\n```swift\nlet oauthScheme = OpenAPI.SecurityScheme.oauth2(\n    flows: .init(\n        implicit: .init(\n            authorizationUrl: URL(string: \"https://my-api.com/oauth2/auth\")!,\n            scopes: [\"read:widget\": \"read widget\"]\n        )\n    )\n)\n```\n\nNext, store it in your OpenAPI document's Components Object (which likely has other entries but we'll only specify the security schemes for this example):\n```swift\nlet components = OpenAPI.Components(\n    securitySchemes: [\"implicit-oauth\": oauthScheme]\n)\n```\n\nFinally, your OpenAPI Document should use the Components Object we just created and also reference the OAuth implicit scheme via an internal JSON reference:\n```swift\nlet document = OpenAPI.Document(\n    info: .init(title: \"API\", version: \"1.0\"),\n    servers: [],\n    paths: [:],\n    components: components,\n    security: [[.component( named: \"implicit-oauth\"): [\"read:widget\"]]]\n)\n```\n\nIf your API supports multiple alternative authentication strategies (only one of which needs to be used), you might have additional entries in your Document's Security array:\n```swift\nlet document = OpenAPI.Document(\n    info: .init(title: \"API\", version: \"1.0\"),\n    servers: [],\n    paths: [:],\n    components: components,\n    security: [\n        [.component( named: \"implicit-oauth\"): [\"read:widget\"]],\n        [.component( named: \"auth-code-oauth\"): [\"read:widget\"]]\n    ]\n)\n```\n\n#### Specification Extensions\nMany OpenAPIKit types support [Specification Extensions](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#specification-extensions). As described in the OpenAPI Specification, these extensions must be objects that are keyed with the prefix \"x-\". For example, a property named \"specialProperty\" on the root OpenAPI Object (`OpenAPI.Document`) is invalid but the property \"x-specialProperty\" is a valid specification extension.\n\nYou can get or set specification extensions via the `vendorExtensions` property on any object that supports this feature. The keys are `Strings` beginning with the aforementioned \"x-\" prefix and the values are `AnyCodable`. If you set an extension without using the \"x-\" prefix, the prefix will be added upon encoding.\n\n`AnyCodable` can be constructed from literals or explicitly. The following are all valid.\n\n```swift\nvar document = OpenAPI.Document(...)\n\ndocument.vendorExtensions[\"x-specialProperty1\"] = true\ndocument.vendorExtensions[\"x-specialProperty2\"] = \"hello world\"\ndocument.vendorExtensions[\"x-specialProperty3\"] = [\"hello\", \"world\"]\ndocument.vendorExtensions[\"x-specialProperty4\"] = [\"hello\": \"world\"]\ndocument.vendorExtensions[\"x-specialProperty5\"] = AnyCodable(\"hello world\")\n```\n\n### Dereferencing \u0026 Resolving\nIn addition to looking something up in the `Components` object, you can entirely derefererence many OpenAPIKit types. A dereferenced type has had all of its references looked up (and all of its properties' references, all the way down).\n\nYou use a value's `dereferenced(in:)` method to fully dereference it.\n\nYou can even dereference the whole document with the `OpenAPI.Document` `locallyDereferenced()` method. As the name implies, you can only derefence whole documents that are contained within one file (which is another way of saying that all references are \"local\"). Specifically, all references must be located within the document's Components Object.\n\nUnlike what happens when you lookup an individual component using the `lookup()` method on `Components`, dereferencing a whole `OpenAPI.Document` will result in type-level changes that guarantee all references are removed. `OpenAPI.Document`'s `locallyDereferenced()` method returns a `DereferencedDocument` which exposes `DereferencedPathItem`s which have `DereferencedParameter`s and `DereferencedOperation`s and so on.\n\nAnywhere that a type would have had either a reference or a component, the dereferenced variety will simply have the component. For example, `PathItem` has an array of parameters, each of which is `Either\u003cOpenAPI.Reference\u003cParameter\u003e, Parameter\u003e` whereas a `DereferencedPathItem` has an array of `DereferencedParameter`s. The dereferenced variant of each type exposes all the same properties and you can get at the underlying `OpenAPI` type via an `underlying{TypeName}` property. This can make for a much more convenient way to traverse a document because you don't need to check for or look up references anywhere the OpenAPI Specification allows them.\n\nFor all dereferenced types, dereferencing will store a new vendor extension on the dereferenced value to keep track of the Component Object name the value used to be referenced at. This vendor extension is a string value with the `x-component-name` key.\n\nYou can take things a step further and resolve the document. Calling `resolved()` on a `DereferencedDocument` will produce a canonical form of an `OpenAPI.Document`. The `ResolvedRoute`s and `ResolvedEndpoint`s that the `ResolvedDocument` exposes collect all relevant information from the whole document into themselves. For example, a `ResolvedEndpoint` knows what servers it can be used on, what path it is located at, and which parameters it supports (even if some of those parameters were defined in an `OpenAPI.Operation` and others were defined in the containing `OpenAPI.PathItem`).\n\nIf your end goal is to analyze the OpenAPI Document or generate something entirely new (like code) from it, the `ResolvedDocument` is by far more convenient to traverse and query than the original `OpenAPI.Document`. The downside is, there is not currently support for mutating the `ResolvedDocument` and then turning it back into an `OpenAPI.Document` to encode it.\n\n```swift\nlet document: OpenAPI.Document = ...\n\nlet resolvedDocument = try document\n    .locallyDereferenced()\n    .resolved()\n\nfor endpoint in resolvedDocument.endpoints {\n    // The description found on the PathItem containing the Operation defining this endpoint:\n    let routeDescription = endpoint.routeDescription\n\n    // The description found directly on the Operation defining this endpoint:\n    let endpointDescription = endpoint.endpointDescription\n\n    // The path, which in the OpenAPI.Document is the key of the dictionary containing\n    // the PathItem under which the Operation for this endpoint lives:\n    let path = endpoint.path\n\n    // The method, which in the OpenAPI.Document is the way you access the Operation for\n    // this endpoint on the PathItem (GET, PATCH, etc.):\n    let httpMethod = endpoint.method\n\n    // All parameters defined for the Operation _or_ the PathItem containing it:\n    let parameters = endpoint.parameters\n\n    // Per the specification, this is \n    // 1. the list of servers defined on the Operation if one is given.\n    // 2. the list of servers defined on the PathItem if one is given _and_ \n    //\tno list was found on the Operation.\n    // 3. the list of servers defined on the Document if no list was found on\n    //\tthe Operation _or_ the PathItem.\n    let servers = endpoint.servers\n\n    // and many more properties...\n}\n```\n\n## Curated Integrations\nFollowing is a short list of integrations that might be immediately useful or just serve as examples of ways that OpenAPIKit can be used to harness the power of the OpenAPI specification.\n\nIf you have a library you would like to propose for this section, please create a pull request and explain a bit about your project.\n\n### Generating Swift\nThe [**swift-openapi-generator**](https://github.com/apple/swift-openapi-generator) uses OpenAPIKit under the hood and generates Swift code for interfacing with APIs that have OpenAPI descriptions.\n\n### Generating OpenAPI Documents\n\n[**VaporOpenAPI**](https://github.com/mattpolzin/VaporOpenAPI) / [VaporOpenAPIExample](https://github.com/mattpolzin/VaporOpenAPIExample) provide an example of generating OpenAPI from a Vapor application's routes.\n\n[**JSONAPI+OpenAPI**](https://github.com/mattpolzin/jsonapi-openapi) is a library that generates OpenAPI schemas from JSON:API types. The library has some rudimentary and experimental support for going the other direction and generating Swift types that represent JSON:API resources described by OpenAPI documentation.\n\n### Declarative OpenAPI Documents\n\nThe [**Swift Package Registry API Docs**](https://github.com/mattt/swift-package-registry-oas) define the OpenAPI documentation for the Swift Package Registry standard using declarative Swift code and OpenAPIKit. This project also provides a useful example of producing a user-friendly ReDoc web interface to the OpenAPI documentation after encoding it as YAML.\n\n### Semantic Diffing of OpenAPI Documents\n\n[**OpenAPIDiff**](https://github.com/mattpolzin/OpenAPIDiff) is a library and a CLI that implements semantic diffing; that is, rather than just comparing two OpenAPI documents line-by-line for textual differences, it parses the documents and describes the differences in the two OpenAPI ASTs.\n\n## Notes\nThis library does *not* currently support file reading at all muchless following `$ref`s to other files and loading them in. You must read OpenAPI documentation into `Data` or `String` (depending on the decoder you want to use) and all references must be internal to the same file to be resolved.\n\nThis library *is* opinionated about a few defaults when you use the Swift types, however encoding and decoding stays true to the spec. Some key things to note:\n\n1. Within schemas, `required` is specified on the property rather than being specified on the parent object (encoding/decoding still follows the OpenAPI spec).\n    * ex `JSONSchema.object(properties: [ \"val\": .string(required: true)])` is an \"object\" type with a required \"string\" type property.\n2. Within schemas, `required` defaults to `true` on initialization (again, encoding/decoding still follows the OpenAPI spec).\n    * ex. `JSONSchema.string` is a required \"string\" type.\n    * ex. `JSONSchema.string(required: false)` is an optional \"string\" type.\n\nSee [**A note on dictionary ordering**](#a-note-on-dictionary-ordering) before deciding on an encoder/decoder to use with this library.\n\n## Contributing\nContributions to OpenAPIKit are welcome and appreciated! The project is mostly maintained by one person which means additional contributors have a huge impact on how much gets done how quickly.\n\nPlease see the [Contribution Guidelines](./CONTRIBUTING.md) for a few brief notes on contributing the the project.\n\n## Security\nThe OpenAPIKit project takes code security seriously. As part of the Swift Server Workground incubation program, this project follows a shared set of standards around receiving, reporting, and reacting to security vulnerabilies.\n\nPlease see [Security](./SECURITY.md) for information on how to report vulnerabilities to the OpenAPIKit project and what to expect after you do.\n\n**Please do not report security vulnerabilities via GitHub issues.**\n\n## Specification Coverage \u0026 Type Reference\nFor a full list of OpenAPI Specification types annotated with whether OpenAPIKit supports them and relevant translations to OpenAPIKit types, see the [Specification Coverage](./documentation/specification_coverage.md) documentation. For detailed information on the OpenAPIKit types, see the [full type documentation](https://github.com/mattpolzin/OpenAPIKit/wiki).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattpolzin%2FOpenAPIKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmattpolzin%2FOpenAPIKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattpolzin%2FOpenAPIKit/lists"}