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

@web-bee-ru/openapi-typescript-codegen

v0.4.12-rc.1

Published

NodeJS library that generates Typescript or Javascript clients based on the OpenAPI specification.

Downloads

2

Readme

OpenAPI Typescript Codegen

NPM License Build Status Codecov Quality

NodeJS library that generates Typescript clients based on the OpenAPI specification.

Why?

  • Frontend ❤️ OpenAPI, but we do not want to use JAVA codegen in our builds.
  • Quick, lightweight, robust and framework agnostic.
  • Supports generation of Typescript clients.
  • Supports generations of fetch and XHR http clients.
  • Supports OpenAPI specification v2.0 and v3.0.
  • Supports JSON and YAML files for input.

Known issues:

  • If you use enums inside your models / definitions then those enums are now inside a namespace with the same name as your model. This is called declaration merging. However, Babel 7 now support compiling of Typescript and right now they do not support namespaces.

Installation

npm install openapi-typescript-codegen --save-dev

Example

package.json

{
    "scripts": {
        "generate": "openapi --input ./api/openapi.json --output ./dist"
    }
}

Command line

npm install openapi-typescript-codegen -g

openapi --input ./api/openapi.json --output ./dist

NodeJS API

const OpenAPI = require('openapi-typescript-codegen');

OpenAPI.generate({
    input: './api/openapi.json',
    output: './generated'
});

Or by providing the JSON directly:

const OpenAPI = require('openapi-typescript-codegen');

const spec = require('./api/openapi.json');

OpenAPI.generate({
    input: spec,
    output: './generated'
});

Features

Argument-style vs. Object-style

There's no named parameter in Javascript or Typescript, because of that, we offer the flag --useOptions to generate code in two different styles.

Argument-style:

function createUser(name: string, password: string, type?: string, address?: string) {
    // ...
}

// Usage
createUser('Jack', '123456', undefined, 'NY US');

Object-style:

function createUser({ name, password, type, address }: {
    name: string,
    password: string,
    type?: string
    address?: string
}) {
    // ...
}

// Usage
createUser({
    name: 'Jack',
    password: '123456',
    address: 'NY US'
});

Runtime schemas

By default the OpenAPI generator only exports interfaces for your models. These interfaces will help you during development, but will not be available in javascript during runtime. However, Swagger allows you to define properties that can be useful during runtime, for instance: maxLength of a string or a pattern to match, etc. Let's say we have the following model:

{
    "MyModel": {
        "required": [
            "key",
            "name"
        ],
        "type": "object",
        "properties": {
            "key": {
                "maxLength": 64,
                "pattern": "^[a-zA-Z0-9_]*$",
                "type": "string"
            },
            "name": {
                "maxLength": 255,
                "type": "string"
            },
            "enabled": {
                "type": "boolean",
                "readOnly": true
            },
            "modified": {
                "type": "string",
                "format": "date-time",
                "readOnly": true
            }
        }
    }
}

This will generate the following interface:

export interface MyModel {
    key: string;
    name: string;
    readonly enabled?: boolean;
    readonly modified?: string;
}

The interface does not contain any properties like maxLength or pattern. However, they could be useful if we wanted to create some form where a user could create such a model. In that form you would iterate over the properties to render form fields based on their type and validate the input based on the maxLength or pattern property. This requires us to have this information somewhere... For this we can use the flag --exportSchemas to generate a runtime model next to the normal interface:

export const $MyModel = {
    properties: {
        key: {
            type: 'string',
            isRequired: true,
            maxLength: 64,
            pattern: '^[a-zA-Z0-9_]*$',
        },
        name: {
            type: 'string',
            isRequired: true,
            maxLength: 255,
        },
        enabled: {
            type: 'boolean',
            isReadOnly: true,
        },
        modified: {
            type: 'string',
            isReadOnly: true,
            format: 'date-time',
        },
    },
};

These runtime object are prefixed with a $ character and expose all the interesting attributes of a model and it's properties. We can now use this object to generate the form:

import { $MyModel } from './generated';

// Some pseudo code to iterate over the properties and return a form field
// the form field could be some abstract component that renders the correct
// field type and validation rules based on the given input.
const formFields = Object.entries($MyModel.properties).map(([key, value]) => (
    <FormField
        name={key}
        type={value.type}
        format={value.format}
        maxLength={value.maxLength}
        pattern={value.pattern}
        isReadOnly={value.isReadOnly}
    />
));

const MyForm = () => (
    <form>
        {formFields}
    </form>
);

Enum with custom names and descriptions

You can use x-enum-varnames and x-enum-descriptions in your spec to generate enum with custom names and descriptions. It's not in official spec yet. But it's a supported extension that can help developers use more meaningful enumerators.

{
    "EnumWithStrings": {
        "description": "This is a simple enum with strings",
        "enum": [
            0,
            1,
            2
        ],
        "x-enum-varnames": [
            "Success",
            "Warning"
            "Error"
        ],
        "x-enum-descriptions": [
            "Used when the status of something is successful",
            "Used when the status of something has a warning"
            "Used when the status of something has an error"
        ]
    }
}

Generated code:

enum EnumWithStrings {
    /*
    * Used when the status of something is successful
    */
    Success = 0,
    /*
    * Used when the status of something has a warning
    */
    Waring = 1,
    /*
    * Used when the status of something has an error
    */
    Error = 2,
}

Authorization

The OpenAPI generator supports Bearer Token authorization. In order to enable the sending of tokens in each request you can set the token using the global OpenAPI configuration:

import { OpenAPI } from './generated';

OpenAPI.TOKEN = 'some-bearer-token';

Compare to other generators

Depending on which swagger generator you use, you will see different output. For instance: Different ways of generating models, services, level of quality, HTTP client, etc. I've compiled a list with the results per area and how they compare against the openapi-typescript-codegen.

Click here to see the comparison