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

openapi-typescript-express

v3.0.2

Published

Generate TypeScript types from Swagger OpenAPI specs suitable for hosting express services

Downloads

522

Readme

openapi-typescript generates TypeScript types from static OpenAPI schemas quickly using only Node.js. It is fast, lightweight, (almost) dependency-free, and no Java/node-gyp/running OpenAPI servers necessary.

The code is MIT-licensed and free for use.

Features

  • ✅ Supports OpenAPI 3.0 and 3.1 (including advanced features like discriminators)
  • ✅ Generate runtime-free types that outperform old-school codegen
  • ✅ Load schemas from YAML or JSON, locally or remotely
  • ✅ Native Node.js code is fast and generates types within milliseconds

Examples

👀 See examples

Usage

First, generate a local type file by running npx openapi-typescript:

# Local schema
npx openapi-typescript ./path/to/my/schema.yaml -o ./path/to/my/schema.d.ts
# 🚀 ./path/to/my/schema.yaml -> ./path/to/my/schema.d.ts [7ms]

# Remote schema
npx openapi-typescript https://myapi.dev/api/v1/openapi.yaml -o ./path/to/my/schema.d.ts
# 🚀 https://myapi.dev/api/v1/openapi.yaml -> ./path/to/my/schema.d.ts [250ms]

⚠️ Be sure to validate your schemas! openapi-typescript will err on invalid schemas.

Then, import schemas from the generated file like so:

import { paths, components } from "./path/to/my/schema"; // <- generated by openapi-typescript

// Schema Obj
type MyType = components["schemas"]["MyType"];

// Path params
type EndpointParams = paths["/my/endpoint"]["parameters"];

// Response obj
type SuccessResponse = paths["/my/endpoint"]["get"]["responses"][200]["content"]["application/json"]["schema"];
type ErrorResponse = paths["/my/endpoint"]["get"]["responses"][500]["content"]["application/json"]["schema"];

🦠 Globbing local schemas

npx openapi-typescript "specs/**/*.yaml" --output schemas/

# 🚀 specs/one.yaml -> schemas/specs/one.ts [7ms]
# 🚀 specs/two.yaml -> schemas/specs/two.ts [7ms]
# 🚀 specs/three.yaml -> schemas/specs/three.ts [7ms]

Thanks, @sharmarajdaksh!

☁️ Remote schemas

npx openapi-typescript https://petstore3.swagger.io/api/v3/openapi.yaml --output petstore.d.ts

# 🚀 https://petstore3.swagger.io/api/v3/openapi.yaml -> petstore.d.ts [250ms]

Thanks, @psmyrdek!

⚾ Fetching data

Fetching data can be done simply and safely using an automatically-typed fetch wrapper:

Example (openapi-fetch)

import createClient from "openapi-fetch";
import { paths } from "./v1"; // (generated from openapi-typescript)

const { get, post, put, patch, del } = createClient<paths>({
  baseUrl: "https://myserver.com/api/v1/",
  headers: {
    Authorization: `Bearer ${import.meta.env.VITE_AUTH_TOKEN}`,
  },
});

See each project’s respective pages for usage & install instructions.

Tip

A good fetch wrapper should never use generics. Generics require more typing and can hide errors!

📖 Options

The following flags can be appended to the CLI command.

| Option | Alias | Default | Description | | :------------------------ | :---- | :------: | :--------------------------------------------------------------------------------------------------------------------------- | | --help | | | Display inline help message and exit | | --version | | | Display this library’s version and exit | | --output [location] | -o | (stdout) | Where should the output file be saved? | | --auth [token] | | | Provide an auth token to be passed along in the request (only if accessing a private schema) | | --header | -x | | Provide an array of or singular headers as an alternative to a JSON object. Each header must follow the key: value pattern | | --headers-object="{…}" | -h | | Provide a JSON object as string of HTTP headers for remote schema request. This will take priority over --header | | --http-method | -m | GET | Provide the HTTP Verb/Method for fetching a schema from a remote URL | | --immutable-types | | false | Generates immutable types (readonly properties and readonly array) | | --additional-properties | | false | Allow arbitrary properties for all schema objects without additionalProperties: false | | --empty-objects-unknown | | false | Allow arbitrary properties for schema objects with no specified properties, and no specified additionalProperties | | --default-non-nullable | | false | Treat schema objects with default values as non-nullable | | --export-type | -t | false | Export type instead of interface | | --path-params-as-types | | false | Allow dynamic string lookups on the paths object | | --support-array-length | | false | Generate tuples using array minItems / maxItems | | --alphabetize | | false | Sort types alphabetically | | --exclude-deprecated | | false | Exclude deprecated fields from types |

🚩 --path-params-as-types

By default, your URLs are preserved exactly as-written in your schema:

export interface paths {
  "/user/{user_id}": components["schemas"]["User"];
}

Which means your type lookups also have to match the exact URL:

import { paths } from "./my-schema";

const url = `/user/${id}`;
type UserResponses = paths["/user/{user_id}"]["responses"];

But when --path-params-as-types is enabled, you can take advantage of dynamic lookups like so:

import { paths } from "./my-schema";

const url = `/user/${id}`;
type UserResponses = paths[url]["responses"]; // automatically matches `paths['/user/{user_id}']`

Though this is a contrived example, you could use this feature to automatically infer typing based on the URL in a fetch client or in some other useful place in your application.

Thanks, @Powell-v2!

🚩 --support-array-length

This option is useful for generating tuples if an array type specifies minItems or maxItems.

For example, given the following schema:

components:
  schemas:
    TupleType
      type: array
      items:
        type: string
      minItems: 1
      maxItems: 2

Enabling --support-array-length would change the typing like so:

  export interface components {
    schemas: {
-     TupleType: string[];
+     TupleType: [string] | [string, string];
    };
  }

This results in more explicit typechecking of array lengths.

Note: this has a reasonable limit, so for example maxItems: 100 would simply flatten back down to string[];

Thanks, @kgtkr!

🐢 Node

npm i --save-dev openapi-typescript
import fs from "node:fs";
import openapiTS from "openapi-typescript";

// example 1: load [object] as schema (JSON only)
const schema = await fs.promises.readFile("spec.json", "utf8"); // must be OpenAPI JSON
const output = await openapiTS(JSON.parse(schema));

// example 2: load [string] as local file (YAML or JSON; released in v4.0)
const localPath = new URL("./spec.yaml", import.meta.url); // may be YAML or JSON format
const output = await openapiTS(localPath);

// example 3: load [string] as remote URL (YAML or JSON; released in v4.0)
const output = await openapiTS("https://myurl.com/v1/openapi.yaml");

⚠️ Note that unlike the CLI, YAML isn’t supported in the Node.js API. You’ll need to convert it to JSON yourself using js-yaml first.

📖 Node options

The Node API supports all the CLI flags above in camelCase format, plus the following additional options:

| Name | Type | Default | Description | | :-------------- | :--------: | :------ | :------------------------------------------------------------------------------- | | commentHeader | string | | Override the default “This file was auto-generated …” file heading | | inject | string | | Inject arbitrary TypeScript types into the start of the file | | transform | Function | | Override the default Schema Object ➝ TypeScript transformer in certain scenarios | | postTransform | Function | | Same as transform but runs after the TypeScript transformation |

🤖 transform / postTransform

Use the transform() and postTransform() options to override the default Schema Object transformer with your own. This is useful for providing non-standard modifications for specific parts of your schema.

  • transform() runs BEFORE the conversion to TypeScript (you’re working with the original OpenAPI nodes)
  • postTransform() runs AFTER the conversion to TypeScript (you’re working with TypeScript types)

For example, say your schema has the following property:

properties:
  updated_at:
    type: string
    format: date-time

By default, openapiTS will generate updated_at?: string; because it’s not sure which format you want by "date-time" (formats are nonstandard and can be whatever you’d like). But we can enhance this by providing our own custom formatter, like so:

const types = openapiTS(mySchema, {
  transform(schemaObject, metadata): string {
    if ("format" in schemaObject && schemaObject.format === "date-time") {
      return schemaObject.nullable ? "Date | null" : "Date";
    }
  },
});

That would result in the following change:

-  updated_at?: string;
+  updated_at?: Date;

Any Schema Object present in your schema will be run through this formatter (even remote ones!). Also be sure to check the metadata parameter for additional context that may be helpful.

There are many other uses for this besides checking format. Because this must return a string you can produce any arbitrary TypeScript code you’d like (even your own custom types).

🏅 Project Goals

  1. Support converting any valid OpenAPI schema to TypeScript types, no matter how complicated.
  2. Generate runtime-free types for maximum performance.
  3. This library does NOT validate your schema, there are other libraries for that.
  4. The generated TypeScript types must match your schema as closely as possible (e.g. no renaming to PascalCase)
  5. This library should never require Java, node-gyp, or some other complex environment to work. This should require Node.js and nothing else.
  6. This library will never require a running OpenAPI server to work.

🤝 Contributing

PRs are welcome! Please see our CONTRIBUTING.md guide.