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

openapi2typescript-cli

v0.7.0

Published

Command line utility to generate [zod](https://github.com/vriad/zod) schemas from an OpenApi schema. These shemas do not only help to have a "typed" response, but they can ensure (by running a validation) that you actually got the type you are expecting.

Downloads

448

Readme

openapi2typescript-cli

Command line utility to generate zod schemas from an OpenApi schema. These shemas do not only help to have a "typed" response, but they can ensure (by running a validation) that you actually got the type you are expecting.

Despite its name, you can also use it in plain js for running the validations (i.e. skip the types generation).

Installing

You can either install openapi2typescript-cli package as a dev-dependency or run it using npx. You are also required to install openapi2typescript as a dependency, as the generated code makes use of that library in most of the cases.

npm install openapi2typescript
npx openapi2typescript-cli 

Usage

To use, you must run the binary npm run openapi2typescript or with npx npx openapi2typescript-cli . You must specify the input file or url to the openapi and the output file, see the Options for more info.

You can see the lib usage at: openapi2typescript

Options

--input

URL or local path to an openapi.json file. If using URL, the Accept: application/json will be provided in the request.

--output

Output file or path to place the result. If using a directory, a file Generated.ts will be created there.

--skip-post-process

Skips the post process which prettier and eslint on the output.

--action-generator

Complementary code to help hook into a third party library, at the moment only react-fetching-library is supported, but more are welcome.

Default: none

none

Does not generate any other code.

react-fetching-library

Generates action generators for react-fetching-library

--add-eslint-disable

Convenient method to disable eslint on the file. i.e. it adds /* eslint-disable */ on top of the file.

--skip-types

Prevent Typescript types from appearing in the output, so that the output is js-friendly.

--no-strict

Use the nonstrict checking behavior of zod for all the objects.

--explicit-types (EXPERIMENTAL)

By default, zod will fail if an object comes with extra properties. With this flag, it won't fail if there are extra properties.

Example

Given the following example:

{
  "openapi" : "3.0.3",
  "info" : {
    "title" : "Generated API",
    "version" : "1.0"
  },
  "paths" : {
    "/fruits" : {
      "get" : {
        "responses" : {
          "200" : {
            "description" : "OK",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SetFruit"
                }
              }
            }
          }
        }
      },
      "post" : {
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/Fruit"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "description" : "OK",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SetFruit"
                }
              }
            }
          }
        }
      },
      "delete" : {
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/Fruit"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "description" : "OK",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/SetFruit"
                }
              }
            }
          },
          "400" : {
            "description" : "Error",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Message"
                }
              }
            }
          }
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Fruit" : {
        "type" : "object",
        "properties" : {
          "description" : {
            "type" : "string"
          },
          "name" : {
            "type" : "string"
          }
        }
      },
      "Message" : {
        "type" : "object",
        "properties" : {
          "description" : {
            "type" : "string"
          }
        }
      },
      "SetFruit" : {
        "uniqueItems" : true,
        "type" : "array",
        "items" : {
          "$ref" : "#/components/schemas/Fruit"
        }
      }
    }
  }
}

Here are some results testing different flags:

Only required arguments:

npx -i openapi.json -o result.ts
/**
 * Generated code, DO NOT modify directly.
 */
import * as z from 'zod';

export const Fruit = zodSchemaFruit();
export type Fruit = z.infer<typeof Fruit>;

export const Message = zodSchemaMessage();
export type Message = z.infer<typeof Message>;

export const SetFruit = zodSchemaSetFruit();
export type SetFruit = z.infer<typeof SetFruit>;

export function zodSchemaFruit() {
    return z.object({
        description: z.string().optional().nullable(),
        name: z.string().optional().nullable()
    });
}

export function zodSchemaMessage() {
    return z.object({
        description: z.string().optional().nullable()
    });
}

export function zodSchemaSetFruit() {
    return z.array(Fruit);
}

With --action-generator react-fetching-library

npx -i openapi.json -o result.ts --action-generator react-fetching-library
/**
 * Generated code, DO NOT modify directly.
 */
import * as z from 'zod';
import { ValidatedResponse } from 'openapi2typescript';
import { Action } from 'react-fetching-library';
import {
    actionBuilder,
    ActionValidatableConfig
} from 'openapi2typescript/react-fetching-library';

export const Fruit = zodSchemaFruit();
export type Fruit = z.infer<typeof Fruit>;

export const Message = zodSchemaMessage();
export type Message = z.infer<typeof Message>;

export const SetFruit = zodSchemaSetFruit();
export type SetFruit = z.infer<typeof SetFruit>;

// GET /fruits
export type GetFruitsPayload =
  | ValidatedResponse<'SetFruit', 200, SetFruit>
  | ValidatedResponse<'unknown', undefined, unknown>;
export type ActionGetFruits = Action<GetFruitsPayload, ActionValidatableConfig>;
export const actionGetFruits = (): ActionGetFruits => {
    const path = '/fruits';
    const query = {} as Record<string, any>;
    return actionBuilder('GET', path)
    .queryParams(query)
    .config({
        rules: [{ status: 200, zod: SetFruit, type: 'SetFruit' }]
    })
    .build();
};

// POST /fruits
export interface PostFruits {
  body: Fruit;
}

export type PostFruitsPayload =
  | ValidatedResponse<'SetFruit', 200, SetFruit>
  | ValidatedResponse<'unknown', undefined, unknown>;
export type ActionPostFruits = Action<
  PostFruitsPayload,
  ActionValidatableConfig
>;
export const actionPostFruits = (params: PostFruits): ActionPostFruits => {
    const path = '/fruits';
    const query = {} as Record<string, any>;
    return actionBuilder('POST', path)
    .queryParams(query)
    .data(params.body)
    .config({
        rules: [{ status: 200, zod: SetFruit, type: 'SetFruit' }]
    })
    .build();
};

// DELETE /fruits
export interface DeleteFruits {
  body: Fruit;
}

export type DeleteFruitsPayload =
  | ValidatedResponse<'SetFruit', 200, SetFruit>
  | ValidatedResponse<'Message', 400, Message>
  | ValidatedResponse<'unknown', undefined, unknown>;
export type ActionDeleteFruits = Action<
  DeleteFruitsPayload,
  ActionValidatableConfig
>;
export const actionDeleteFruits = (
    params: DeleteFruits
): ActionDeleteFruits => {
    const path = '/fruits';
    const query = {} as Record<string, any>;
    return actionBuilder('DELETE', path)
    .queryParams(query)
    .data(params.body)
    .config({
        rules: [
            { status: 200, zod: SetFruit, type: 'SetFruit' },
            { status: 400, zod: Message, type: 'Message' }
        ]
    })
    .build();
};

export function zodSchemaFruit() {
    return z.object({
        description: z.string().optional().nullable(),
        name: z.string().optional().nullable()
    });
}

export function zodSchemaMessage() {
    return z.object({
        description: z.string().optional().nullable()
    });
}

export function zodSchemaSetFruit() {
    return z.array(Fruit);
}

--skip-types

npx -i openapi.json -o result.js --skip-types
/**
 * Generated code, DO NOT modify directly.
 */
import * as z from 'zod';

export const Fruit = zodSchemaFruit();

export const Message = zodSchemaMessage();

export const SetFruit = zodSchemaSetFruit();

export function zodSchemaFruit() {
    return z.object({
        description: z.string().optional().nullable(),
        name: z.string().optional().nullable()
    });
}

export function zodSchemaMessage() {
    return z.object({
        description: z.string().optional().nullable()
    });
}

export function zodSchemaSetFruit() {
    return z.array(Fruit);
}

--explicit-types

npx -i openapi.json -o result.ts --explicit-types
/**
 * Generated code, DO NOT modify directly.
 */
import * as z from 'zod';

export const Fruit = zodSchemaFruit();
export type Fruit = {
  description?: string | undefined | null;
  name?: string | undefined | null;
};

export const Message = zodSchemaMessage();
export type Message = {
  description?: string | undefined | null;
};

export const SetFruit = zodSchemaSetFruit();
export type SetFruit = Array<Fruit>;

export function zodSchemaFruit() {
    return z.object({
        description: z.string().optional().nullable(),
        name: z.string().optional().nullable()
    });
}

export function zodSchemaMessage() {
    return z.object({
        description: z.string().optional().nullable()
    });
}

export function zodSchemaSetFruit() {
    return z.array(Fruit);
}

--action-generator react-fetching-library --skip-types

npx -i openapi.json -o result.js --action-generator react-fetching-library --skip-types
/**
 * Generated code, DO NOT modify directly.
 */
import * as z from 'zod';
import { actionBuilder } from 'openapi2typescript/react-fetching-library';

export const Fruit = zodSchemaFruit();

export const Message = zodSchemaMessage();

export const SetFruit = zodSchemaSetFruit();

// GET /fruits
export const actionGetFruits = () => {
    const path = '/fruits';
    const query = {};
    return actionBuilder('GET', path)
    .queryParams(query)
    .config({
        rules: [{ status: 200, zod: SetFruit, type: 'SetFruit' }]
    })
    .build();
};

// POST /fruits
/*
 Params
body: Fruit
*/
export const actionPostFruits = (params) => {
    const path = '/fruits';
    const query = {};
    return actionBuilder('POST', path)
    .queryParams(query)
    .data(params.body)
    .config({
        rules: [{ status: 200, zod: SetFruit, type: 'SetFruit' }]
    })
    .build();
};

// DELETE /fruits
/*
 Params
body: Fruit
*/
export const actionDeleteFruits = (params) => {
    const path = '/fruits';
    const query = {};
    return actionBuilder('DELETE', path)
    .queryParams(query)
    .data(params.body)
    .config({
        rules: [
            { status: 200, zod: SetFruit, type: 'SetFruit' },
            { status: 400, zod: Message, type: 'Message' }
        ]
    })
    .build();
};

export function zodSchemaFruit() {
    return z.object({
        description: z.string().optional().nullable(),
        name: z.string().optional().nullable()
    });
}

export function zodSchemaMessage() {
    return z.object({
        description: z.string().optional().nullable()
    });
}

export function zodSchemaSetFruit() {
    return z.array(Fruit);
}