Coder Social home page Coder Social logo

luxoft / gengen Goto Github PK

View Code? Open in Web Editor NEW
17.0 17.0 7.0 907 KB

Tool for generating models and Angular services based on OpenAPIs and Swagger's JSON.

License: MIT License

TypeScript 99.87% JavaScript 0.13%
angular code-generation codegenerator swagger typescript

gengen's People

Contributors

aborisovdubna avatar akhromets avatar aleshadk avatar aleshchev avatar dependabot[bot] avatar jackkk94 avatar jeremiah avatar klimenkoav avatar llotall avatar nikitaegorov avatar sevaru avatar zaostrovskii avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gengen's Issues

Develop policy for creating and using secrets in Luxoft repos

Is your feature request related to a problem? Please describe.
The goal is to publish gengen to npmjs.org to include it in the Node ecosystem of packages. To do so we need to have an authorization token from Node.

Describe the solution you'd like
We need to establish a policy for handling secrets in general and for npmjs.org specifically. Reusing GitHub's secrets API seems like a good approach and ought to be evaluated.

Separate services for same endpoint name

Describe the bug
For the same endpoint name with different HTTP verbs gengen generates separate services:
image

To Reproduce
here is the minimal "path" section

"paths": {
    "/sample/test": {
      "get": {
        "tags": [
          "sample"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "sample"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      },
      "put": {
        "tags": [
          "sample"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      },
      "delete": {
        "tags": [
          "sample"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    }
}

results in swagger
image

Expected behavior
Gengen generates only one service with different methods

Additional context
Such "paths" can be generated by ASP minimal API:

var group = app.MapGroup("sample").WithTags("sample");
group.MapGet("test", () => "test");
group.MapPost("test", () => {});
group.MapPut("test", () => {});
group.MapDelete("test", () => {});

Terminology for OSS request

In the second issue the output we create from the Luxoft web app reads;

**Usage type**
 - [ ] Distributed separately - not bundled with proprietary software
 - [X] Distributed bundled with proprietary software
 - [ ] I will host the open source for access by clients
 - [ ] Modified
 - [ ] Embedded
 - [X] Linked

The problem is the term "bundled" has no legal meaning. Words matter a great deal in the law and our liability remains the same whether we're describing it correctly or not. In this case, we're not describing it accurately. The GPL uses the term "aggregation" to describe "bundling"; " In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License." Therefor, I propose changing our wording to "Aggregated and distributed with proprietary software."

The same issue applies to the terms "clients", "embedded" and even "linked", at least with regard to the GPL and software development.

Error copying base ts libs after generation

Describe the bug
Error copying base ts libs to output directory after generation

Error:
Error: ENOENT: no such file or directory, copyfile 'D:\src\my-app\libs\date-converters.ts' -> 'D:\src\my-app\src\generated\date-converters.ts'
Error: ENOENT: no such file or directory, copyfile 'D:\src\my-app\libs\base-http.service.ts' -> 'D:\src\my-app\src\generated\base-http.service.ts'
Error: ENOENT: no such file or directory, copyfile 'D:\src\my-app\libs\mappers.ts' -> 'D:\src\my-app\src\generated\mappers.ts'
..etc

To Reproduce
Run:
gengen ver. 1.0.0-rc.0
openapi.json - openapi v3 version file

gengen g --all --file openapi.json --output ./src/generated

Expected behavior
Base libs copied to output directory

Add CONTRIBUTING.md

  1. Git flow
  2. If you will develop new feature then you need to update swagger.json
  3. Tests (e2e, unit)
  4. Good PR naming (Git commit generator)
  5. Well done

Fetch for domian objects that in ValueObject types doesn't work

Describe the bug
For example, we have class that has value object type property

public class DomainClass1 : AuditPersistentDomainObjectBase 
{
    public virtual Component? Component { get; set; }
}

// where Component is 
public class Component : ValueObject
{
    public virtual DomainClass2? DomainClass2 { get; protected set; }
}

And fetch for this classes structure doesn't work, inspite on Nnhibernate Support.

...
bll.GetUnsecureQueryable(f => f.SelectNested(x => x.Component ).Select(x => x!.DomainClass2)).ToList();
...

As result low performance and big amount of useless requests.

To Reproduce
For reproducing use same classes structure as described above

Expected behavior
Fetch must work, amount of requests to database must decrease

Error generating methods with path parameters

Describe the bug
Generating query parameters for methods with path parameters.

To Reproduce
gengen ver. 1.0.0-rc.1
Method parameter in openapi json file marks as path type

{
  "paths": {
    "/Product/Download/{id}": {
          "get": {
            "tags": [
              "Product"
            ],
            "parameters": [
              {
                "name": "id",
                "in": "path",
                "required": true,
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Success"
              }
            }
          }
        }
    }
}
...

Actual behavior

public download(id: string): Observable<void> {
        return this.get<void>(
            `download?id=${encodeURIComponent(id)}`,
        );
    }

Expected behavior

public download(id: string): Observable<void> {
        return this.get<void>(
            `download/${encodeURIComponent(id)}`,
        );
    }

Incorrect relative path if app has baseHref that different then /

Describe the bug
The tool generates relative paths which is not correct if application has baseHref (you can see it in base element) different then simple slash (/)

To Reproduce
Just run ng build --prod --base-href /somePath/

Expected behavior
Tool generates relative paths something like /somePath/api/v1/Something

Actual behavior
Tool generates relative paths /api/v1/Something

Simple params in body request ignored

Describe the bug
Simple params in body request ignored

To Reproduce

"requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      }
    },

Expected behavior
generate method with parameter

Additional context
parameter is not generated

A way to set compile time absolute basePath for some swagger endpoints

Is your feature request related to a problem? Please describe.
As for now there is no way to generate angular services which would request to different domain
Example.
// my app is hosted on
https://myapp/
// I need to request external api from
https://someweatherapp/api/

Describe the solution you'd like
Config option basePath (or maybe absoluteBasePath)

gengen --basePath https://myapiurl/api --url https://myswaggerurl/swagger.json

Fix config generation formatting

Describe the bug
endpoint.config.ts generation now has bad formatting

Current

export class Endpoints {
  public static CategoryService = {
        AddCategory: 'Category/AddCategory'
     };
}

Expected

export class Endpoints {
  public static CategoryService = {
     AddCategory: 'Category/AddCategory'
  };
}

Add support for url parameters

Generator does not generate methods who parameters placed in URL. Need to add support.
Example

"/api/v1/Product/Product/{id}": {
      "get": {
        "tags": [
          "Product"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          }
        }
      }
    },

Reduce generated code, in case with microservices architecture

I've microservices architecture, that means I've several swagger.json sources.
Nowadays, GenGen would generates utilities files per each swagger.json.

Solution
I want to have possibility generate utils one time and then shared between generated code.

Documentation

Create a detailed project guide

  1. what the project does
  2. best practices for use

Allow to override method code generators

Is your feature request related to a problem? Please describe.
In some projects I want to generate string url for GET download methods instead of downloading them async

Describe the solution you'd like
I would like to provide my custom generator to override existing

Allow to pass request options (for CORS scenarios)

Is your feature request related to a problem? Please describe.
When we use gengen in CORS scenario we might need to send withCredentials=true

Describe the solution you'd like
As a solution we propose to

  1. create additional option for generation (gengen --generateMethodsWithOptions, or maybe some other option name)
  2. when option is set to true an additional parameter is added to every generated method
// before
    public searchProducts(name: string): Observable<$models.Product[]> {
        //...
    }

// after 
   public searchProducts(name: string, options?: IAngularHttpRequestOptions): Observable<$models.Product[]> {
         //...
    }

Example

productService.searchProduct('search string', { withCredentials: true }) //...

Optional query parameters

Describe the bug
I can't use query optionally parameters when I don't need past them

Expected behavior
Query string without empty (null or undefined) parameters

New generation option: GuidType=string | Guid

Is your feature request related to a problem? Please describe.
I have a project with a lot of places that uses id as string, but gengen generates id as Guid model.
By these reason for using of generator i should make a lot of changes in my code for properly compilation without errors.

Describe the solution you'd like
I offer to add a new option that will switch generation of guid to string

GenGen ~ Roadmap

TODO

  1. Start use swaggerService to properly define API
  2. Definite swaggerService contracts
  3. #20
    --
  4. In/Out in models, do not generate interfaces for identities?
  5. Sample Dotnet + Swagger project

Questions

  1. Abstract render?
  2. Support migration from swagger to swagger?

Terminology

Endpoint - concrete url

Model - enum(s), DTO(s)

EndpointsConfig - typescript file to select endpoints for generation

Сервисы

SwaggerService

// hides work with swagger.json
// ~ api
getEndpoints
getModels
getModelByName
getEndpointByName
getEndpointModels

IModelMetadata
IEndpointMetadata

GlueService

// works with SwaggerService to get some dependencies (e.g. get all models (fields) by model)
TODO: proper name, api
getModelsByEndpoints

ModelRenderService // could different implementation for angular, vue, react

dependency: SwaggerService
generate(models: IModel[])

EndpointsRenderService // could different implementation for angular, vue, react

dependency: SwaggerService
generate(endpoints: IEndpoints[])

EndpointsConfigRenderService

dependency: SwaggerService

ModelsConfigRenderService // maybe to generate only models

dependency: SwaggerService

EndpointsConfigReader // gets method list from endpoints.config.ts

API USAGES

generate facade

const endpointsConfigRenderService = new EndpointsConfigRenderService({
  swaggerService,
});
/*
swaggerService.getEndpoints()
*/
endpointsConfigRenderService.render();

generate endpoints (all, by facadeConfig)

const endpointsRenderService = new EndpointsRenderService({
  swaggerService,
});

if (options.all) {
  endpointsRenderService.renderAll();
} else {
  const endpointsList = endpointsConfigReader.getEndpoints();
  endpointsRenderService.render(endpointsList);
}

generate models

const modelRenderService = new ModelRenderService({ swaggerService });

// TODO: proper name of service?
const models = glueService.getModelsByEndPoints(endpoints); 

modelRenderService.generate(models);

Adding of the Put method

Is your feature request related to a problem? Please describe.
I wanted to use put method for implementation of the update endpoints with PUT header

Describe the solution you'd like
Add to BaseHttpService PUT method

Can't generate methods with enum path/query params

Describe the bug
If you URI has enum as a parameter in query or in path then gengen could't fails to generate anything

It's appears after #53 feature implementation

To Reproduce

"/api/v1/Product/GetProductsByStatus/{status}": {
      "get": {
        "tags": [
          "Product"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ProductStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              }
            }
          }
        }
      }
    },

Expected behavior

gengen g 

should not throw an error

Usage of multiple swagger endpoint in one angular project + CORS endpoints

Is your feature request related to a problem? Please describe.
As for now we can't generate multiple services/models to one directory.
And can't generate services which would use dynamic basePath CORS endpoints

Describe the solution you'd like
As a solution we suggests

  1. options aliasName that would be used in services/models filenames
  2. global variable (e.g. __gengen__basePathMap) with map of alias <-> basePath (e.g. { ['myalias']: 'https://myapibasepath.com/api' }

Error casting parameters after generation

Describe the bug
services.ts has models casting errors after generation (for base .post and .downloadFile methods in generated BaseHttpService and DownloadFileService services)

To Reproduce
gengen ver. 1.0.0-rc.0
openapi.json - openapi v3 version file

Run:
gengen g --all --file openapi.json --output ./src/generated

Error:
Argument of type 'IModelDTO' is not assignable to parameter of type 'Record<string, unknown>'

Handle paths without methods

For example

"/api/v1/Product": {
      "get": {
        "tags": [
          "Product"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Product"
                  }
                }
              }
            }
          }
        }
      }
    }

#1196 CodeSynthesis XSD

There are two issues with the 1196 request;

  1. The project adds and exception to the GPL
  2. The request is ambiguous with regard to "derived work."

In the first issue, the license for the XSD software has an additional exception in front of the GPLv2 (GPL version 2 only). In general, additional restrictions are not allowed to the GPL; "Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions." However, the XSD program comes with an exception, not a restriction. The intent of the exception is here: https://git.codesynthesis.com/cgit/xsd/xsd/tree/FLOSSE

Question: Is this exception acceptable? I believe it is acceptable for our usage scenario.

In the second issue the output we create from the Luxoft web app reads;

**Usage type**
 - [ ] Distributed separately - not bundled with proprietary software
 - [X] Distributed bundled with proprietary software
 - [ ] I will host the open source for access by clients
 - [ ] Modified
 - [ ] Embedded
 - [X] Linked

The problem is the term "bundled" has no legal meaning. Words matter a great deal in the law and our liability remains the same whether we're describing it correctly or not. In this case, we're not describing it accurately. The GPL uses the term "aggregation" to describe "bundling"; " In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License." Therefor, I propose changing our wording to "Aggregated and distributed with proprietary software."

The same issue applies to the terms "clients", "embedded" and even "linked", at least with regard to the GPL and software development. Those I will file as separate issues.

Call stack was exceeded when there are hierarchical models

Describe the bug
There are model which referenced to itself

To Reproduce

"TreeModel": {
        "type": "object",
        "properties": {
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TreeModel"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },

enum generated as model

Describe the bug
Response model has enum and generator identify it like model

To Reproduce

"SomeResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "$ref": "#/components/schemas/SomeStatus"
          },
          "telegramBotId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "additionalProperties": false
      },
      "SomeStatus": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "format": "int32"
      },

Expected behavior
in generated model created enum SomeStatus

Additional context
Backend use minimal api

Wrong sorting when generating enums

Describe the bug
Wrong sorting when generating enums

To Reproduce
gengen ver. 1.0.0-rc.0
openapi.json - openapi v3 version file

Run
gengen g --all --file openapi.json --output ./src/generated

enum config from openapi v3 json file

....
"EntityStatus": {
        "enum": [
          0,
          1,
          2,
          3,
          -2,
          -1
        ],
        "type": "integer",
        "format": "int32",
        "x-enumNames": [
          "Candidate",
          "Active",
          "OnProbationPeriod",
          "OnTermination",
          "Canceled",
          "Terminated"
        ]
      },
...

Actual output Result:

export enum EntityStatus {
    Candidate = -1,
    Active = -2,
    OnProbationPeriod = 0,
    OnTermination = 1,
    Canceled = 2,
    Terminated = 3
}

Expected behavior
Expected output Result:

export enum EntityStatus {
  Candidate = 0,
  Active = 1,
  OnProbationPeriod = 2,
  OnTermination = 3,
  Canceled = -2,
  Terminated = -1
}

Add support for upload files

Generator does not support upload files yet.
Example multipart form data

"/api/v1/Category/Upload": {
      "post": {
        "tags": [
          "Category"
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "ContentType": {
                    "type": "string",
                    "nullable": true
                  },
                  "ContentDisposition": {
                    "type": "string",
                    "nullable": true
                  },
                  "Headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "nullable": true
                  },
                  "Length": {
                    "type": "integer",
                    "format": "int64"
                  },
                  "Name": {
                    "type": "string",
                    "nullable": true
                  },
                  "FileName": {
                    "type": "string",
                    "nullable": true
                  },
                  "name": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "encoding": {
                "ContentType": {
                  "style": "form"
                },
                "ContentDisposition": {
                  "style": "form"
                },
                "Headers": {
                  "style": "form"
                },
                "Length": {
                  "style": "form"
                },
                "Name": {
                  "style": "form"
                },
                "FileName": {
                  "style": "form"
                },
                "name": {
                  "style": "form"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            }
          }
        }
      }
    }

Wrong generation of List<DateTime> fields

Describe the bug
For list of date times on backend
public List<DateTime> ProcessingDates { get; set; }

GenGen generates wrong mapping of array of date times.

To Reproduce

{
    "processingDates": [
      "2021-11-12T13:04:23.572Z",
      "2021-11-13T14:14:22.572Z"
    ]
}

Expected behavior
Mapping of Dates in Model should be like this:
in toDTO method
processingDates: model.processingDates.map(toDateOut),

in fromDTO method:
model.processingDates = dto.processingDates.map(toDateIn);

Additional context
Generation result:
Interface: IColumnFilterDataModel
image
Class: ColumnFilterDataModel
image

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.