Coder Social home page Coder Social logo

swagger-to-flowtype's Introduction

swagger-to-flowtype

swagger-to-flowtype is a tool for generating type definitions of Flow from swagger file.

Getting started

Install package

npm i -g swagger-to-flowtype

Generating flow type definitions

$swagger-to-flowtype <YOUR SWAGGER FILE OR URL>

This command generates a file named flowtype.js includes type definitions as default.

Options

Specify an output path

You can also specify an output path with -d option.

$swagger-to-flowtype <YOUR SWAGGER FILE PATH OR URL> -d <OUTPUT FILE PATH>

Supporting Maybe type

If you pass a --check-required option, swagger-to-flowtype will check required field on your swagger file, then output flow definitions with Maybe type.

"NewPet": {
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string"
    },
    "tag": {
      "type": "string"
    }
  }
}

will be

export type NewPet = {
  name: string,
  tag?: string
}

Transform property key to lower camel case

--lower-camel-case option transforms each property keys to lower camel case.

"Cat": {
  "type": "object",
  "properties": {
    "long_long_key": {
      "type": "string"
    }
  }
}

will be

export type Cat = { longLongKey?: string };

Example

swagger file like following

...

definitions:
  Order:
    type: "object"
    properties:
      id:
        type: "integer"
        format: "int64"
      petId:
        type: "integer"
        format: "int64"
      quantity:
        type: "integer"
        format: "int32"
      shipDate:
        type: "string"
        format: "date-time"
      status:
        type: "string"
        description: "Order Status"
        enum:
        - "placed"
        - "approved"
        - "delivered"
      complete:
        type: "boolean"
        default: false
    xml:
      name: "Order"
  Category:
    type: "object"
    properties:
      id:
        type: "integer"
        format: "int64"
      name:
        type: "string"
    xml:
      name: "Category"
...

Output will be like below

// @flow
export type Order = {
  id: number,
  petId: number,
  quantity: number,
  shipDate: string,
  status: 'placed' | 'approved' | 'delivered',
  complete: boolean
};
export type Category = { id: number, name: string };

Requirements

Node 4+ is required

Tests

npm test

swagger-to-flowtype's People

Contributors

callmeberzerker avatar dawsbot avatar dependabot[bot] avatar desmondhume avatar hssrrw avatar jkawamoto avatar keitamoromizato avatar lockonostratos avatar maccuaa avatar pwfcurry avatar rgraffbrd avatar sodik avatar thetfo avatar yayoc avatar yskoht avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

swagger-to-flowtype's Issues

Optional object type properties

Is it supported as of now? It seems like there's no check on the required field of swagger manifest.

For example:

{
  "definitions": {
    "User": {
      "type": "object",
      "required": [
        "email"
      ],
      "properties": {
        "username": {
          "type": "string",
          "description": "User username"
        },
        "email": {
          "type": "string",
          "description": "User email"
        }
      }
    }
  }
}

should output:

export type User = {
  username?: string,
  email: string
};

Do you think a PR might be helpful?

This tool is super useful for me at the moment 😄

Undesirable Flow type being generated from OpenAPI's `oneOf` keyword.

Consider the following OpenAPI schema:

{
    "openapi": "3.0.1",
    "paths": {
        "/v1/tool/breadcrumbs/{hierarchyId}/{categoryId}": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Get Breadcrumbs details",
                "operationId": "getBreadcrumbs",
                "parameters": [
                    {
                        "name": "hierarchyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    },
                    {
                        "name": "categoryId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Kitten"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        },
        "/v1/tool/hierarchies": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Get all available hierarchies ",
                "operationId": "getAllHierarchies",
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/HierarchyResponse"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        },
        "/v1/tool/search/{hierarchyId}/{searchTerm}": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Free text search categories for a given hierarchy",
                "operationId": "searchBy",
                "parameters": [
                    {
                        "name": "hierarchyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    },
                    {
                        "name": "searchTerm",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Kitten"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        },
        "/v1/tool/category/{hierarchyId}/{categoryId}": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Get Category data needed to render a Table View in the Category Management tool",
                "operationId": "getTableView",
                "parameters": [
                    {
                        "name": "hierarchyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    },
                    {
                        "name": "categoryId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TableViewResponse"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "Kitten": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Kitten"
                        ]
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "name": {
                        "type": "string"
                    },
                    "uri": {
                        "type": "string"
                    }
                }
            },
            "HierarchyResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Hierarchy"
                        ]
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "name": {
                        "type": "string"
                    }
                }
            },
            "AliasCategoryResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Alias"
                        ]
                    },
                    "level": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "uri": {
                        "type": "string"
                    }
                }
            },
            "ChildCategoryResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Category"
                        ]
                    },
                    "level": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "uri": {
                        "type": "string"
                    }
                }
            },
            "GblSubheaderResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Translation"
                        ]
                    },
                    "brandCatalogId": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "value": {
                        "type": "string"
                    }
                }
            },
            "Item": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string"
                    }
                },
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/ChildCategoryResponse"
                    },
                    {
                        "$ref": "#/components/schemas/AliasCategoryResponse"
                    },
                    {
                        "$ref": "#/components/schemas/SubheaderResponse"
                    }
                ]
            },
            "ParentCategoryResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "ParentCategory"
                        ]
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "name": {
                        "type": "string"
                    }
                }
            },
            "SubheaderResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Subheader"
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "translatedNames": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GblSubheaderResponse"
                        }
                    }
                }
            },
            "TableViewResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "DefaultCategory"
                        ]
                    },
                    "uri": {
                        "type": "string"
                    },
                    "level": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "parentCategory": {
                        "$ref": "#/components/schemas/ParentCategoryResponse"
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Item"
                        }
                    }
                }
            }
        },
        "securitySchemes": {
            "Auth": {
                "type": "http",
                "description": "Token Authentication  e.g. Bearer <placeholder>",
                "scheme": "bearer",
                "bearerFormat": "JWT"
            }
        }
    }
}

The problem is that the Item type is defined as:

export type Item = { type: string };

And we'd like it to be defined instead as:

export type Item = ChildCategoryResponse | AliasCategoryResponse | SubheaderResponse

The relevant part of our OpenAPI schema is:

"Item": {
    "type": "object",
    "properties": {
        "type": {
            "type": "string"
        }
    },
    "oneOf": [
        {
            "$ref": "#/components/schemas/ChildCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/AliasCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/SubheaderResponse"
        }
    ]
},

I posted this Stack Overflow question and was informed that "oneOf and type are not supposed to be used together" and when replacing the above Item definition in OpenAPI schema with the following:

"Item": {
    "oneOf": [
        {
            "$ref": "#/components/schemas/ChildCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/AliasCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/SubheaderResponse"
        }
    ],
    "discriminator": {
        "propertyName": "type",
        "mapping": {
            "Category": {
                "$ref": "#/components/schemas/ChildCategoryResponse"
            },
            "Alias": {
                "$ref": "#/components/schemas/AliasCategoryResponse"
            },
            "Subheader": {
                "$ref": "#/components/schemas/SubheaderResponse"
            }
        }
    }
},

swagger-typescript-api then outputs export type Item = ChildCategoryResponse | AliasCategoryResponse | SubheaderResponse; as Item's type definition while swagger-to-flowtype outputs export type Item = {};.

If we created a PR that solves this issue, would you be open to reviewing it?

`allOf` ignores `properties`

If we derive a model from another using allOf rule, everything declared under properties will be ignored.

Example input:

    ImageEditable:
      type: object
      properties:
        description:
          type: string
          maxLength: 200
        id:
          type: string
          maxLength: 32
    Image:
      allOf:
        - $ref: '#/components/schemas/ImageEditable'
      type: object
      properties:

        ext:
          type: string
          maxLength: 10
        filelink:
          type: string

Current output:

export type ImageEditable = { description: string, id: string };
export type Image = ImageEditable;

Expected output:

export type ImageEditable = { description: string, id: string };
export type Image = { description: string, id: string, ext: string, filelink: string  };

I guess, it's because propertiesList() immediately returns if definition.allOf found. Without processing definition.properties.

const propertiesList = (definition: Object) => {
if ("allOf" in definition) {
return definition.allOf.map(propertiesList);
}

Generating client classes

Has there been consideration around creating the actual client classes using the proper HTTP method and URL? The swagger-codegen for typescript has a few different flavors, depending on what you want to use for your http library.

I'd like to use Axios, personally, but we could add arguments to specify different libraries. What do you think of something like this?

Write to file with same root file name

swagger.json currently gets flowtypes named flowtype.js.

It should instead be something akin to the original name, such that in the future, this package can take multiple files or a directory as input.

I propose swagger.json -> swagger.js

Issues with generic definitions

If I have definitions such as

Customer: { ... },
IPage[Customer]: { ... },
User: { ...  },
IPage[User] { ... }

This causes an error.

I attempted to solve this by putting in code to replace [ and ] with < and >, however flow doesn't appear to support exporting multiple generic implementations of a class.

export type Customer = {...};
export type IPage<Customer> = {...}
export type User = {...}
export type IPage<User> = {...}

I know this is a bit vague, but I didn't have time to scrub together an example. Hopefully this makes sense.

Another possible option, that's not too crazy, would be to drop the last bracket and replace the first with an underscore:

export type Customer = {...};
export type IPage_Customer = {...}
export type User = {...}
export type IPage_User = {...}

What are your thoughts? How does the swagger typescript generator handle this?

Swagger file version required ?

Hi,

I'd like to use your lib, but, is there any minimum version required for the Swagger file ?
Mine is 1.1, and it seems that your lib is not compatible with this version (searching for definitions field)

Should we upgrade to another version ?

Specifying prefix / suffix for flow type

I was very pleased to find this library as it does a nice job of generating flow types from an OpenApi schema.

One thing that is missing for me is being able to change the name of the flow type to include a prefix or suffix (different projects I have worked on use one or the other).

ie. changing a schema definition named User:

  • with a type prefix like TUser
  • with a type suffix like UserT

I think this would be covered by adding two additional arguments to the program to take a string and modify the name in all definitions & "$ref" positions.

Are you be open to a PR that addresses this?

SyntaxError: Unexpected character

Hello!
Gives an error when generated:
No parser and no filepath given, using 'babel' the parser now but this will throw an error in the future. Please specify a parser or a filepath so one can be inferred. SyntaxError: Unexpected character '«'

There is such a code in JSON:
"GetPricing«Restrictions»": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" }, "values": { "$ref": "#/definitions/Restrictions" } }, "title": "GetPricing«Restrictions»" },

If I remove it, I get this error:
No parser and no filepath given, using 'babel' the parser now but this will throw an error in the future. Please specify a parser or a filepath so one can be inferred. SyntaxError: Unexpected token, expected "," (2:3592)
But on the second line is this:
"swagger": "2.0",

What is the reason?

Support $Exact utility type

Sometimes, disabling width subtyping is useful for Object type and Type Alias by using $Exact utility type.
Also, I think that an adding a --exact option into a command to specify if run this feature is convenient.

Here is an example.
run $swagger-to-flowtype --exact will generate

export type User = {|
  username: string,
  email: string
|};

oneOf in OAS3 not supported

Consider the following OAS3:

openapi: 3.0.0
components:
  schemas:
    ArticleFraud:
      type: object
      properties:
        reason:
          type: string
    UserFraud:
      type: object
      properties:
        reason:
          type: string
    FraudCase:
      type: object
      properties:
        id:
          type: number
        metadata:
          oneOf:
            - $ref: '#/components/schemas/ArticleFraud'
            - $ref: '#/components/schemas/UserFraud'

Fails with: TypeError: Cannot read property 'match' of undefined in https://github.com/yayoc/swagger-to-flowtype/blob/master/src/index.js#L25

Dashes (-) in component names will make prettier crash

components:
  schema:
    My-Awesome-Type:
      type: object
      properties:
        foo:
          type: string
{ SyntaxError: Unexpected token, expected "=" (2:20)
.../node_modules/swagger-to-flowtype/node_modules/prettier/parser-babylon.js:1:326

Even though prettier is the module crashing I think that this needs to be addressed in swagger-to-flowtype, because export type My-Awesome-Type = {} is invalid JS to begin with.

Dashes are supported in OpenAPI spec (3.0.2): https://swagger.io/docs/specification/components/

The component names can consist of the following characters only:
A..Z a..z 0..9 . _ -

Running on Windows, shebang causes issues

I'm not entirely sure how to fix this yet, I get an error:

/c/Users/anthony.foster/AppData/npm/swagger-to-flowtype: line 12: /usr/local/bin/node: No such file or directory

I'm sure this is due to Windows, and changing the shebang to:

/usr/local/bin node

may help.

Support reading from URLs

Using a URL doesn't work

$ swagger-to-flowtype http://localhost:8000/api/swagger
{ Error: ENOENT: no such file or directory, open 'http://localhost:8000/api/swagger'
    at Object.fs.openSync (fs.js:663:18)
    at Object.fs.readFileSync (fs.js:568:33)
    at generator (/home/nulldivision/Projects/MyProject/node_modules/swagger-to-flowtype/dist/index.js:146:35)
    at Command.<anonymous> (/home/nulldivision/Projects/MyProject/node_modules/swagger-to-flowtype/dist/index.js:170:18)
    at Command.listener (/home/nulldivision/Projects/MyProject/node_modules/commander/index.js:300:8)
    at emitOne (events.js:125:13)
    at Command.emit (events.js:221:7)
    at Command.parseArgs (/home/nulldivision/Projects/MyProject/node_modules/commander/index.js:637:12)
    at Command.parse (/home/nulldivision/Projects/MyProject/node_modules/commander/index.js:457:21)
    at Object.<anonymous> (/home/nulldivision/Projects/MyProject/node_modules/swagger-to-flowtype/dist/index.js:177:4)
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'http://localhost:8000/api/swagger' }

Feature request: Flow-strict

It would be dandy to use @flow strict instead of @flow. There's other options such as @flow strict-local, but since the files emitted by swagger-to-flowtype don't require any other files, we can safely skip to just using @flow strict.

As I understand, using @flow strict won't inflict anything upon a non-strict project. For those of us using strict it means the files won't be considered non-strict. All that is to say I don't think we really need a configuration option for it, since the behavior is backwards compatible.

Thanks for all the work on this repo!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.