Git Product home page Git Product logo

flowup / api-client-generator Goto Github PK

View Code? Open in Web Editor NEW
116.0 116.0 22.0 2.76 MB

Angular REST API client generator from Swagger YAML or JSON file with camel case settigs

License: MIT License

TypeScript 99.36% HTML 0.01% JavaScript 0.12% Handlebars 0.51%
angular angular-http angular9 api generator httpclient json models ngx rest rest-api scaffolding swagger swagger-yaml typescript yaml

api-client-generator's People

Contributors

admir86 avatar azuka avatar biophoton avatar edbzn avatar kubaj avatar mrkpks avatar paveltobias avatar resistancecanyon avatar vmasek avatar warmans 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

api-client-generator's Issues

[Enums] property names first letters shouldn't be lowercase

Current behavior example

export enum PickUpTime {
  pUT_ANYTIME = "PUT_ANYTIME",
  pUT_MORNING = "PUT_MORNING",
  pUT_AFTERNOON = "PUT_AFTERNOON",
}

Desired behavior example

export enum PickUpTime {
  PUT_ANYTIME = "PUT_ANYTIME",
  PUT_MORNING = "PUT_MORNING",
  PUT_AFTERNOON = "PUT_AFTERNOON",
}

[api-client] autocommit

The generator should be able to automatically commit its output if asked.

  • The commit message should briefly summarize what has been generated.
  • The author of the commit message will be set to a name descriptive of the generator (e.g. api-client-generator, API Client Generator, ...) and a unique, possibly ficticious, email ([email protected], [email protected]). This way it will be distinguishable which changes in the repo were generated and which were made manually by a human contributor.
  • The autocommit will be performed only if
    1. the --commit or -C flag is provided to the generator and
    2. the repository has no staged changes.

The nodegit library will be used for Git operations. Git operations should be executed using Git's CLI in child processes. This is to reduce unnecessary dependencies and avoid problems with installing nodegit on some systems.

Observable.throw() is deprecated

In private sendRequest() method:

throw is deprecated: In favor of throwError creation function: import { throwError } from 'rxjs';

support for embedded models

It would be cool if the API client could generate also embedded models with tag allOf, because now is ignoring this field.

example:

definitions:
    model:
      type: "object"
      properties:
        id:
          type: "string"
        created:
          type: "integer"
        updated:
          type: "integer"
        deleted:
          type: "integer"
    customer:
      type: "object"
      allOf:
      - $ref: "#/definitions/model"
      properties:
        name:
          type: "string"
        address:
          type: "string"

[api-client] method names

some of the method names are generated with the name like
gET_somethingList should be full camelcase without the underscored prefix

Type Errors

Hi,

I'm having some issues with my generated code. On build I get a bunch of errors like:

.../api-client-service.ts(379,59): error TS2345: Argument of type 'HttpOptions' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
  Types of property 'responseType' are incompatible.
    Type '"text" | "arraybuffer" | "blob" | "json"' is not assignable to type '"json"'.
      Type '"text"' is not assignable to type '"json"'.

This seem to me like it's probably a versioning issue, e.g. the typescript or angular versions are wrong. I'm using Angular 4.x.x with typescript 2.4.0. I tried angular 5.x.x and TS 2.6.x and has the same issues. Maybe the code you generate targets an older angular version?

Additionally HttpObserve is not exported in /common/http. To get the generated code to build at all I've edited the HttpOptions interface as follows:

interface HttpOptions {
  headers?: HttpHeaders,
  params?: HttpParams,
  reportProgress?: boolean,
  withCredentials?: boolean,
}

Any ideas?

[models] ItemModelList and ItemList definitions in swagger.json create the same file

The following type definitions create the same file and the 2nd one overwrites the first:

"ItemList": {
      "description": "List of items",
      "required": [
        "data"
      ],
      "type": "object",
      "properties": {
        "data": {
          "description": "List of controllers in the system (this can be empty)",
          "type": "array",
          "items": {
            "$ref": "#/definitions/Data"
          }
        },
      }
"ItemModelList": {
      "description": "List of Item models",
      "required": [
        "data"
      ],
      "type": "object",
      "properties": {
        "data": {
          "description": "The list of available ItemModels and their configurations",
          "type": "array",
          "items": {
            "$ref": "#/definitions/DataModel"
          }
        },
      }
    }

The problem is in 'helper.ts', line 80:

export function fileName(name: string = '', type: 'model' | 'enum' = 'model'): string {
  return `${dashCase(name.replace(/model|enum/i, ''))}.${type}`;
}

The 'model' part of the definition name is removed by the replace function and therefore:
ItemModelList becomes ItemList, the same name as the other existing type ItemList and the original model file is overwritten.

Empty model

If I create API call post with empty body EmptyProtobuf it should place in call {} as a body instead of creating EmptyProtonufModel and passing it as a parameter in the function.

multi import of same interface

when you generate an interface and there are same interfaces used in it, it adds the same number of imports as is the number of interfaces in the interface.

typescript ->

import { MyAwesomeModel } from './my-awesome-model.model'
import { MyAwesomeModel } from './my-awesome-model.model'
import { MyAwesomeModel } from './my-awesome-model.model'

export interface MySecondAwesomeModel {
item1: MyAwesomeModel;
item2: MyAwesomeModel;
item3: MyAwesomeModel;
}

swagger ->

mySecondAwesome:
type: "object"
properties:
item1:
$ref: "#/definitions/myAwesome"
item2:
$ref: "#/definitions/myAwesome"
item3:
$ref: "#/definitions/myAwesome"

[Generator] recursive interfaces

if generated interface contains itself in a recursive way, there is an unnecessary import

import {
  Discussion
} from '..';

export interface Discussion {
  authorName: string;
  comments: Discussion[];
  date: string;
}

2.1.1 Is missing a template file

It looks like ngx-module-export.mustache does not exist in the released version?

/usr/bin/ngx-swag-client -> /usr/lib/node_modules/@flowup/ngx-swagger-client-generator/dist/main.js
+ @flowup/[email protected]
added 26 packages in 6.849s
Error encored during generating { Error: ENOENT: no such file or directory, open '/usr/lib/node_modules/@flowup/ngx-swagger-client-generator/dist/../templates/ngx-module-export.mustache'
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/usr/lib/node_modules/@flowup/ngx-swagger-client-generator/dist/../templates/ngx-module-export.mustache' }

Add tests for multiple swaggers

  • provide multiple swagger files that will cover supported features
  • push reference outputs
  • create test cases based on folder diffs

Feature Idea - Global TakeUntil

So the situation is you have a page which contains a bunch of components that might be executing API requests at any time. You then have an event that means you need to just kill everything and take the user somewhere else (e.g. their token expired and you just want to take them back to a login page).

So the current way to do this is to have a ngDestroy on each component that handles the cancellation of the request either by directly unsubscribing or managing a local takeUntil.

But I think it would be possible to implement a generic solution to this since takeUntil is implemented before subscribe so the generated sendRequest method could just attach a takeUntil to all observables allowing api requests to be globally cancelled via a single event emitter.

Or something like - if an emitter is injected then it adds the takeUntil otherwise it just does the normal thing.

What do you think?

Consumes - application/json not being passed to APIClient

Hello,

Just wondering if it's intended that the swagger property:

 "consumes": [
                    "application/json"
                ]

is meant to be ignored when generated the API client? I assumed a header would of been generated & applied to API services which have this property? Right now we are adding it to the NGModule as a universal header, but some API Client calls don't use application/json.

Is this intended behaviour or a bug?

Thanks =).

How to re-generate example client?

Is the swagger file missing to regenerate the example code (example dir in project)? Additionally it seems like this target is not functional in the package.json:

    "gen": "ts-node ./src/main.ts",

I guess it should be ...main.ts -s the-missing-swagger-file.json -o example.

[api-client] method parameter non referred enums

method parameters that are enums but not referenced or listed in parameters schema are not generated properly. The enum type is used instead of enum itself.
In this example swagger we can see the enum properties but parameter orderBy is generated as a string (which is non-breaking but incorrect)

Argument names do not always match path placeholders in generated code

With the latest released version it seems like there is a discrepancy between how arg properties and placeholders are formatted e.g.

  createCustomerInvite(
    args: {
      customerId: string,
      body: models.V2CreateCustomerInviteRequest,
    },
    options?: HttpOptions
  ): Observable<models.V2Invite> {
    const path = `/api/v2/customers/${args.customer_id}/invites`;
    options = {...this.options, ...options};

    return this.sendRequest<models.V2Invite>('POST', path, options, JSON.stringify(args.body));
  }

customerId becomes customer_id in the path.

the swagger definition:

        "/api/v2/customers/{customer_id}/invites": {
            "post": {
                "description": "Create an invite for a new customer user.",
                "tags": [
                    "invite",
                    "admin"
                ],
                "summary": "Create an invite for a customer",
                "operationId": "CreateCustomerInvite",
                "parameters": [
                    {
                        "type": "string",
                        "name": "customer_id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v2CreateCustomerInviteRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "schema": {
                            "$ref": "#/definitions/v2Invite"
                        }
                    }
                }
            }
        },

[ApiClientService] Imports

  • there are imported unused interfaces
  • when tsconfig option noUnusedParameters is used the compilation will fail

Option to Observe/Return entire Response

The generator should have an option from each api function to pass on an option whether to return the entire response for one use case and/or to return the expected response data.
Currently the response body is what we're getting/observing.

@vmasek @gelidus
IMO the default value returned should be simplistic as to return the response body alone for most of the use cases.

Expected code snapshot when observing the entire response in

private sendRequest
function

private sendRequest<T>(method: string, uri: string, headers: HttpHeaders, params: HttpParams, body: any): Observable<HttpResponse<T>> { if (method === 'get') { return this.http.get<T>(this.domain + uri, { headers: headers.set('Accept', 'application/json'), params: params, observe: 'response' }); } }

[Generator] dash case type naming

when using dash case naming (for example in the file name of an interface), ones with all-caps abbreviations like ID, are generated like foo-i-d-bar instead of foo-id-bar

BASIC_TS_TYPE_REGEX

Hi flowup,

In my swagger file I have a type, which contains the letters 'any' in it. Your pattern matches this type against BASIC_TS_TYPE_REGEX. Here is the word: Tanulmany
See below my fix for this.
Regards, adamzoltan

old
const BASIC_TS_TYPE_REGEX = /^string|number|integer|boolean|null|undefined|any|Object|Date|File|Blob$/;
new
const BASIC_TS_TYPE_REGEX = /\b(string|number|integer|boolean|null|undefined|any|Object|Date|File|Blob)\b/;

Error encored during generating TypeError: type.toLocaleLowerCase is not a function

Steps:

After installing api-client-generator ran api-client-generator -s ./api.yaml -o ./apidocs.

Assumptions:
YAML is valid.
No errors during installation.

Angular CLI: 6.0.7
Node: 10.2.1
OS: darwin x64
Angular: 6.0.3
  • angular-devkit/architect 0.6.8
  • angular-devkit/build-angular 0.6.8
  • angular-devkit/build-optimizer 0.6.8
  • angular-devkit/core 0.6.8
  • angular-devkit/schematics 0.6.7 (cli-only)
  • angular/cli 6.0.7
  • ngtools/webpack 6.0.8
  • schematics/angular 0.6.7 (cli-only)
  • schematics/update 0.6.7 (cli-only)
  • rxjs 6.2.1
  • typescript 2.7.2
  • webpack 4.8.3

Stack trace shown:

Error encored during generating TypeError: type.toLocaleLowerCase is not a function
at Object.toTypescriptType (/usr/local/lib/node_modules/api-client-generator/dist/helper.js:46:21)
at /usr/local/lib/node_modules/api-client-generator/dist/parser.js:109:39
at Array.map ()
at parseInterfaceProperties (/usr/local/lib/node_modules/api-client-generator/dist/parser.js:106:39)
at defineInterface (/usr/local/lib/node_modules/api-client-generator/dist/parser.js:161:22)
at defineEnumOrInterface (/usr/local/lib/node_modules/api-client-generator/dist/parser.js:75:11)
at /usr/local/lib/node_modules/api-client-generator/dist/parser.js:62:16
at Array.map ()
at parseDefinitions (/usr/local/lib/node_modules/api-client-generator/dist/parser.js:60:10)
at createMustacheViewModel (/usr/local/lib/node_modules/api-client-generator/dist/parser.js:18:22)

Any input is more than welcomed.

Cheers.

[api-client] array params methods should use append instead of set

here is an example swagger parameter definition:

{
  "type": "array",
  "items": {
    "type": "string"
  },
  "name": "filters",
  "in": "query"
}

and here is what gets generated for that parameter

  listThings(filters: string[], options?: HttpOptions): Observable<models.V2RuleList> {
    const path = `/api/v2/things`;
    options = {...this.options, ...options};

    if (filters) {
      options.params = options.params.set('filters', String(filters));
    }
    return this.sendRequest<models.V2ThingList>('GET', path, options);
  }

The filters array ends up being joined with commas.

What should happen:

The generated code for the param should look more like this:

    if (filters) {
      filters.forEach(v => {
        options.params = options.params.append('filters', v);
      });
    }

This is unfortunately arguable since apparently there is not a clear standard. However multiple params with the same name is the most and reliable approach AFAIK so it should probably be used.

The functionality could be hidden behind a flag for backwards compatibility i.e. it uses set by default but append if --append-array-params is supplied during generation.

[Enum] generation of wrong enum name

If you have an enum in a separate file it generates correctly but importing it somewhere will cause misnaming it should generate xxxEnum but it generates xxxModel and even file path is wrong.

[models] generate interface with map attribute

Properties with additionalProperties should be generated as the keymap

Example
INPUT:

myInterface:
  type: "object"
  properties:
    myName:
      type: "string"
    myId:
      type: "string"
    myMap:
      type: "object"
      additionalProperties:
        $ref: "#/definitions/someOtherInterface"

OUTPUT:

export interface MyInterface {
  myName: string;
  myId: string;
  myMap: {[key: string]: SomeOtherInterface};
}

(bug) HttpOptions.headers:HttpHeaders compatibility issue with aot compilation

Running
$ ng build --prod
while the module is injected to the app.
We get the following error

ERROR in app/app.module.ts(14,21): Error during template compile of 'AppModule' Function calls are not supported in decorators but 'HttpHeaders' was called.

This might be due to the fact that simple assignments are only allowed during module declarations.
and we're trying to pass new HttpHeaders(...header String/objects) into the module declaration.

Possible Solution:

  • Add a new optional config headersConfig into HttpOptions, which will be the input signature of HttpHeaders() constructor
  • Make it working with this way as well.

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.