npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@criteria/openapi

v0.9.3

Published

TypeScript implementation of the OpenAPI specification.

Downloads

167

Readme

OpenAPI

TypeScript type definitions and functions for the OpenAPI specification.

Table of Contents

Overview

This package provides TypeScript type definitions and functions for working with OpenAPI documents. It is intended to be used by tooling authors, to build OpenAPI tools in TypeScript across various versions of the specification easily.

This package also contains functions to dereference OpenAPI documents into plain JavaScript objects according to the reference resolution rules of the specification.

The following versions are currently supported:

Getting Started

Install OpenAPI using npm:

npm install @criteria/openapi

Let's define a minimal OpenAPI document in code to get started:

import { OpenAPI } from '@criteria/openapi/v3.1'

const openAPI: OpenAPI = {
  openapi: '3.1.0',
  info: {},
  paths: {
    '/people': {
      get: {
        responses: {
          '200': {
            $ref: '#/components/responses/PersonList'
          }
        }
      }
    }
  },
  components: {
    responses: {
      PersonList: {
        description: 'List of person objects',
        content: {
          'application/json' {
            schema: {
              type: 'array',
              items: {
                $ref: '#/components/schemas/Person'
              }
            }
          }
        }
      }
    },
    schemas: {
      Person: {
        type: 'object',
        title: 'person',
        properties: {
          name: {
            $ref: '#/$defs/requiredString'
          },
          email: {
            $ref: '#/$defs/requiredString'
          }
        },
        $defs: {
          requiredString: {
            title: 'requiredString',
            type: 'string',
            minLength: 1
          }
        }
      }
    }
  }
}

Right now if we tried to inspect any responses of the GET /people operation we would get undefined:

console.log(openAPI.paths['/people'].get.responses['200'].content)
// undefined

We can use the dereferenceOpenAPI() function to transform our OpenAPI object with $ref values into plain JavaScript objects without any references:

import { OpenAPI, DereferencedOpenAPI, dereferenceOpenAPI } from '@criteria/openapi/v3.1'

const openAPI: OpenAPI = {
  /* same as above */
}

const dereferencedOpenAPI: DereferencedOpenAPI = dereferenceOpenAPI(openAPI)

console.log(JSON.stringify(openAPI.paths['/people'].get.responses['200'].content['application/json']))
// prints the Person schema

The return type of dereferenceOpenAPI(openAPI) is DereferencedOpenAPI instead of OpenAPI. This is a TypeScript type alias that replaces Reference objects with their dereferenced values.

JSON Schema compatibility

The OpenAPI specification makes use of the JSON Schema specification to describe Schema objects, with some modifications. Starting with v3.1, the OpenAPI specification also supports explicitly specifying which dialect of JSON Schema to use, both globally using the jsonSchemaDialect field and per schema using the $schema keyword.

This package's supports of JSON Schema is described in this table:

| OpenAPI version | JSON Schema draft | Modifications | | --------------- | ----------------- | ------------------------------------------------------------------------------------------ | | v3.1 | Draft 2020-12 | See the Schema object specification. | | v3.0 | Draft 04 | See the Schema object specification. |

Installation

npm install @criteria/openapi

Usage

Importing type definitions

Type names are suffixed with the version that they correspond to:

import { OpenAPIv3_0, OpenAPIv3_1 } from '@criteria/openapi'

const fooOpenAPI: OpenAPIv3_0 = {
  openapi: '3.0.3'
}

const barOpenAPI: OpenAPIv3_1 = {
  openapi: '3.1.0'
}

If you only want to import types for a specific version, you can import more concise types from the version-specific module:

import { OpenAPI } from '@criteria/openapi/v3.0'

const openAPI: OpenAPI = {
  openapi: '3.0.3'
}
import { OpenAPI } from '@criteria/openapi/v3.1'

const openAPI: OpenAPI = {
  openapi: '3.1.0'
}

The webhooks field is a new field introduced in version 3.1. Trying to define webhooks on a v3.0 document is caught by the TypeScript compiler:

import { OpenAPIv3_0 } from '@criteria/json-schema'

const openAPI: OpenAPIv3_0 = {
  webhooks: {}
}
// 'webhooks' does not exist in type 'OpenAPI<Reference>'

Dereferencing OpenAPI documents

Dereferencing refers to the process of transforming an OpenAPI document by replacing occurences of $ref with the actual component being referenced.

The dereferenceOpenAPI(openAPI) functions provided by this package observe the following behaviour:

  • The OpenAPI document is treated as immutable. The return value is a copy of the input data.
  • Object identity is maintained. The dereferenced OpenAPI document is the same JavaScript instance as the value that was referenced.
  • Circular references are preserved. Recursive or circular references in the input OpenAPI document will be replicated in the dereferenced output.

The following example demonstrates this behaviour:

import { dereferenceOpenAPI } from '@criteria/openapi/v3.1'

const inputOpenAPI: OpenAPI = {
  openapi: '3.1.0'
  components: {
    schemas: {
      Person: {
        type: 'object',
        title: 'person',
        properties: {
          name: {
            $ref: '#/components/schemas/RequiredString'
          },
          children: {
            type: 'array',
            items: {
              $ref: '#/components/schemas/Person'
            }
          }
        }
      },
      RequiredString: {
        title: 'requiredString',
        type: 'string',
        minLength: 1
      }
    }
  }
}

const dereferencedOpenAPI = dereferenceOpenAPI(inputOpenAPI)

console.log(dereferencedOpenAPI === inputOpenAPI)
// false, input data is not mutated

console.log(dereferencedOpenAPI.components.schemas['Person'].properties.name === dereferencedOpenAPI.components.schemas['RequiredString'])
// true, object identity is maintained

console.log(dereferencedOpenAPI.components.schemas['Person'].properties.children.items === dereferencedOpenAPI.components.schemas['Person'])
// true, circular references are supported

Retrieving external documents

It's common for API definition authors to organize complex OpenAPI definitions as multiple shared files. You can provide a custom retrieve function to dereferenceOpenAPI() in order to perform an filesystem or network operations.

The following example dereferences an OpenAPI document that references other files as relative paths from the same directory.

import { readFileSync } from 'fs'

const baseURI = resolve(__dirname, 'openapi.json')

const retrieve = (uri: string) => {
  const data = readFileSync(uri, { encoding: 'utf8' })
  return JSON.parse(data)
}

const dereferencedSchema = dereferenceJSONSchema(rootSchema, { baseURI, retrieve })

The argument passed to your retrieve function is a URI that has been resolved according to the base URI that you specified. Note that this URI is an identifier and not necessarily a network locator. In the case of a network-addressable URL, a schema need not be downloadable from its canonical URI.

Acknowledgments

Many test cases have been ported from @apidevtools/json-schema-ref-parser.

License

This project is MIT licensed.

About Criteria

Criteria is a collaborative platform for designing APIs.

Two types of tooling

  • WOrking with OpenAPI documents - serializing, bundling, importing exporting
  • Working with OpenAPI data at runtime, request/response validation, codegen etc.

Foundational types to serve both use cases OpenAPI, DereferencedOpenAPI DereferencedOpenAPI substitutes never for Reference, so you' don't need to to tahype narrowing in code hooks, onDereference() -> stash serialization context

@criteria/openapi

TypeScript type definitions and functions for the OpenAPI specification.

  • TypeScript support, including type narrowing.
  • Immutable values
  • Sync or async
  • Validation
  • DereferencedOpenAPI distinct to OpenAPI

Getting Started

npm install @criteria/openapi

Usage

import { OpenAPI } from '@criteria/openapi'

Usage

  • Validating objects conform to interface
    • Obtaining validators
  • Working with references

    • Dereferencing

Accessing TypeScript types

import { OpenAPI } from '@criteria/openapi'

const openAPI: OpenAPI = {
    ...
}

Narrow values to OpenAPI types using the isOpenAPI function.

import { OpenAPI, isOpenAPI } from '@criteria/openapi'

const value: any = // ...

if (isOpenAPI(value)) {
  // value is OpenAPI
}
import { OpenAPI, isOpenAPI, strictValidator } from '@criteria/openapi'

if (isOpenAPI(value, { validator: strictValidator })) {
  // value is OpenAPI
}

You can access specific versions of the specification.

import { OpenAPI as OpenAPIv3_0, isOpenAPI as isOpenAPIv3_0 } from '@criteria/openapi/v3.0'
import { OpenAPI as OpenAPIv3_1, isOpenAPI as isOpenAPIv3_1 } from '@criteria/openapi/v3.1'

Validating objects conform to the OpenAPI specification

import { validateOpenAPI, ValidationError } from '@criteria/openapi'

const value: any = // ...

try {
    validateOpenAPI(value)
    const validOpenAPI = value as OpenAPI
    // value is OpenAPI
} catch (error: ValidationError) {

}

Dereferencing OpenAPI objects

TypeScript type predicates

import { OpenAPI, isOpenAPI } from '@criteria/openapi'

isOpenAPI(obj, { validate: false }) // default
isOpenAPI(obj, { validate: true }) // equivalent to isOpenAPI(obj, { validate: validateOpenAPI })
isOpenAPI(obj, { validate: (obj) => { ... } })

// Example
const obj: unknown = {... }
if (isOpenAPI(obj)) {
    // obj is OpenAPI
}

Validating

import { OpenAPI, validateOpenAPI } from '@criteria/openapi'

const obj: unknown = {... }
if (validateOpenAPI(obj)) {
    // obj is OpenAPI
}

validateOpenAPI(obj, { strict: false }) // default
validateOpenAPI(obj, { strict: true, validateExtension: (field, value, object, pointer) })

Obtaining validators

const strictValidator = openAPIValidator({ strict: true })
strictValidator(obj)

Type-safe dereferenced objects

import { OpenAPI, DereferencedOpenAPI } from '@criteria/openapi'

const openAPI: OpenAPI = { ... }
const schema = openAPI.components.schema // Schema | Reference

const dereferencedOpenAPI: DereferencedOpenAPI = { ... }
const schema = dereferencedOpenAPI.components.schema // Schema

Dereferencing

import { DereferencedOpenAPI, isDereferencedOpenAPI, validateDereferencedOpenAPI } from '@criteria/openapi'
const dereferencedOpenAPI = dereferenceOpenAPI(openAPI)
const dereferencedOpenAPI = dereferenceOpenAPI(openAPI, { retrieve: (uri) => object })