kogosoftwarellc / open-api

A Monorepo of various packages to power OpenAPI in node
MIT License
892 stars 235 forks source link

openapi-types: Extract HTTP methods to enum to allow programmatic access #713

Closed Envek closed 3 years ago

Envek commented 3 years ago

If I want programmatically inspect or preprocess spec, then I'm in trouble when I want to iterate over all possible HTTP methods inside every path, I have to duplicate list of HTTP from spec's PathItemObject verbs in my code, and after that TypeScript will throw an error because it can't figure out that all of array elements are declared in PathItemObject type definition:

import { OpenAPIV3 } from "openapi-types"

const apiSpec: <OpenAPIV3.Document> = { … }

for (const methods of Object.values(schema.paths)) {
    for (const method of ["get", "post", "put", "delete", "options", "head", "patch", "trace"]) {
      const pathItem = methods[method] // ERROR!
      //               ~~~~~~~~~~~~~~~
      // Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'PathItemObject'.
      //   No index signature with a parameter of type 'string' was found on type 'PathItemObject'. ts(7053)

Thankfully, in TypeScript we can declare enums and use their keys and values in runtime, like this:

enum HttpMethods {
    GET = 'get',
    PUT = 'put',
    POST = 'post',
    DELETE = 'delete',
}

Object.values(HttpMethods).map(values => …)

So, by adding such an enum and rewriting PathItemObject using it as index signature, we can do following:

import { OpenAPIV3 } from "openapi-types"

const apiSpec: <OpenAPIV3.Document> = { … }

for (const methods of Object.values(schema.paths)) {
    for (const method of Object.values(OpenAPIV3.HttpMethods)) {
      const pathItem = methods[method] // ok, method definitely is one of HttpMethods values and pathItem is a pathItemObject

Sure, I can define such an enum in my code (and add some additional type casting), but I think that keeping it in the package is the right thing.

As a side effect, PathItemObject definitions became a little bit more self-documented (here are metadata and here are http verbs with corresponding OperationObjects).

Notes