Giter VIP home page Giter VIP logo

swagger-typescript-codegen's Introduction

Swagger to Typescript Codegen

Build Status

This package generates a TypeScript class from a swagger specification file. The code is generated using mustache templates and is quality checked by jshint and beautified by js-beautify.

The typescript generator is based on superagent and can be used for both nodejs and the browser via browserify/webpack.

This fork was made to simplify some parts, add some more features, and tailor it more to specific use cases.

Installation

npm install swagger-typescript-codegen

Example

var fs = require("fs");
var CodeGen = require("swagger-typescript-codegen").CodeGen;

var file = "swagger/spec.json";
var swagger = JSON.parse(fs.readFileSync(file, "UTF-8"));
var tsSourceCode = CodeGen.getTypescriptCode({
  className: "Test",
  swagger: swagger,
  imports: ["../../typings/tsd.d.ts"]
});
console.log(tsSourceCode);

Custom template

var source = CodeGen.getCustomCode({
  moduleName: "Test",
  className: "Test",
  swagger: swaggerSpec,
  template: {
    class: fs.readFileSync("my-class.mustache", "utf-8"),
    method: fs.readFileSync("my-method.mustache", "utf-8"),
    type: fs.readFileSync("my-type.mustache", "utf-8")
  }
});

Options

In addition to the common options listed below, getCustomCode() requires a template field:

template: { class: "...", method: "..." }

getTypescriptCode(), getCustomCode() each support the following options:

moduleName:
  type: string
  description: Your module name
className:
  type: string
beautify:
  type: boolean
  description: whether or not to beautify the generated code
beautifyOptions:
  type: object
  description: Options to be passed to the beautify command. See js-beautify for all available options.
mustache:
  type: object
  description: See the 'Custom Mustache Variables' section below
imports:
  type: array
  description: Typescript definition files to be imported.
convertQueryParamsToFormDataInPOST:
  type: boolean
  description: whether or not to convert query parameters in a POST request to form data.
swagger:
  type: object
  required: true
  description: swagger object

Template Variables

The following data are passed to the mustache templates:

isES6:
  type: boolean
description:
  type: string
  description: Provided by your options field: 'swagger.info.description'
isSecure:
  type: boolean
  description: false unless 'swagger.securityDefinitions' is defined
moduleName:
  type: string
  description: Your module name - provided by your options field
className:
  type: string
  description: Provided by your options field
domain:
  type: string
  description: If all options defined: swagger.schemes[0] + '://' + swagger.host + swagger.basePath
methods:
  type: array
  items:
    type: object
    properties:
      path:
        type: string
      pathFormatString:
        type: string
      className:
        type: string
        description: Provided by your options field
      methodName:
        type: string
        description: Generated from the HTTP method and path elements or 'x-swagger-js-method-name' field
      method:
        type: string
        description: 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'COPY', 'HEAD', 'OPTIONS', 'LINK', 'UNLINK', 'PURGE', 'LOCK', 'UNLOCK', 'PROPFIND'
        enum:
        - GET
        - POST
        - PUT
        - DELETE
        - PATCH
        - COPY
        - HEAD
        - OPTIONS
        - LINK
        - UNLINK
        - PURGE
        - LOCK
        - UNLOCK
        - PROPFIND
      isGET:
        type: string
        description: true if method === 'GET'
      summary:
        type: string
        description: Provided by the 'description' or 'summary' field in the schema
      externalDocs:
        type: object
        properties:
          url:
            type: string
            description: The URL for the target documentation. Value MUST be in the format of a URL.
            required: true
          description:
            type: string
            description: A short description of the target documentation. GitHub-Markdown syntax can be used for rich text representation.
      isSecure:
        type: boolean
        description: true if the 'security' is defined for the method in the schema
      version:
        type: string
        description: Version part of the path, if the path starts with the prefix '/api/vXXX/'.
      intVersion:
        type: integer
        description: Integer part of the version string.
      isLatestVersion:
        type: boolean
        description: True iff this is the latest version of the method.
      parameters:
        type: array
        description: Includes all of the properties defined for the parameter in the schema plus:
        items:
          camelCaseName:
            type: string
          isSingleton:
            type: boolean
            description: true if there was only one 'enum' defined for the parameter
          singleton:
            type: string
            description: the one and only 'enum' defined for the parameter (if there is only one)
          isBodyParameter:
            type: boolean
          isPathParameter:
            type: boolean
          isQueryParameter:
            type: boolean
          isPatternType:
            type: boolean
            description: true if *in* is 'query', and 'pattern' is defined
          isHeaderParameter:
            type: boolean
          isFormParameter:
            type: boolean
          collectionFormat:
            type: string
      successfulResponseType:
        type: string
        description: The type of a successful response. Defaults to any for non-parsable types or Swagger 1.0 spec files
      successfulResponseTypeIsRef:
        type: boolean
        description: True iff the successful response type is the name of a type defined in the Swagger schema.
      convertQueryParamsToFormDataInPOST:
        type: boolean
        description: Provided by your options field

Custom Mustache Variables

You can also pass in your own variables for the mustache templates by adding a mustache object:

var source = CodeGen.getCustomCode({
    ...
    mustache: {
      foo: 'bar',
      app_build_id: env.BUILD_ID,
      app_version: pkg.version
    }
});

Swagger Extensions

x-proxy-header

Some proxies and application servers inject HTTP headers into the requests. Server-side code may use these fields, but they are not required in the client API.

eg: https://cloud.google.com/appengine/docs/go/requests#Go_Request_headers

  /locations:
    get:
      parameters:
      - name: X-AppEngine-Country
        in: header
        x-proxy-header: true
        type: string
        description: Provided by AppEngine eg - US, AU, GB
      - name: country
        in: query
        type: string
        description: |
          2 character country code.
          If not specified, will default to the country provided in the X-AppEngine-Country header
      ...

Development

To run the typescript compiler on the source files run. This will start a watch process on the sources and build them into the lib folder.

npm run build:watch

In addition you can run the test watcher in a separate tab to run the tests in watch mode on the files in the lib folder.

npm run test:watch

swagger-typescript-codegen's People

Contributors

andy-viv avatar andyperlitch-turnto avatar bartlomn avatar biggora avatar borisirota avatar bradygaster avatar chdanielmueller avatar chrisjamesc avatar erictuvesson avatar hacklone avatar kosta-github avatar legneato avatar mahnunchik avatar markionium avatar mgmarino avatar mshustov avatar mtennoe avatar nalbion avatar pizzapete avatar rajit avatar sassanh avatar sbusch avatar scott-c avatar scott-campbell-carsales-com-au avatar scottc avatar sibbl avatar sjwilczynski avatar tido64 avatar tommyseus avatar wcandillon 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

swagger-typescript-codegen's Issues

Property 'default' does not exist on type 'SuperAgentStatic'

I generated some code, and it fails the Typescript build with

Property 'default' does not exist on type 'SuperAgentStatic'

The code in question is

    const agent = this.configureAgentHandler ?
        this.configureAgentHandler(request.default) :
        request.default;

It seems that the default property doesn't exist according to @types/superagent.

At first glance this issue seems to have been introduced by this change. I can't find a related issue or any other context on that change, but it's clearly a deliberate change that fixed some other problem.

I'm using Superagent v5.1.0 and @types/superagent v4.1.3.

Path params not uri encoded.

The path appended to the domain may contain strings that have special characters but are not uri encoded.

queryParameters[parameterName] = parameters[parameterName];

An example of this could be
'/someurl/{SomeParam}' evaluating to '/someurl/Some/Param' if SomeParam is 'Some/Param'

This would result in a bad request, where the backend may be expecting something like "Some/Param", for which the request should look like '/someurl/Some%2FParam'

redux-saga integration

I'm using swagger-typescript-codegen along side redux-saga.

For every swagger api I need to write some additional repetitive boilerplate code (action types, watcher generator functions and saga generator functions), to integrate the apis into my codebase.

It would be nice if this additional code was also generated for me.

It's beyond the scope of swagger-typescript-codegen, to have redux-saga integration.

I'm unsure if this can be achieved using the existing templates.

But it would be nice to have an extension, supplementary tool or documentation, that would help facilitate this.

[feature] concise response type alias

The response types can be quite long, and inconvenient to use.

const x: Promise<ResponseWithBody<200, OkBody> | ResponseWithBody<404, NotFoundBody> | ResponseWithBody<400, BadRequestBody>> = undefined;

I propose generating some concise type aliases.

type SomeAlias1 = ResponseWithBody<200, OkBody>;
type SomeAlias2 = ResponseWithBody<404, NotFoundBody>;
type SomeAlias3 = ResponseWithBody<400, BadRequestBody>;

type SomeUnionResponseAlias = SomeAlias1 | SomeAlias2 | SomeAlias3;

The alias's should be backwards compatible, optional to use and work as drop in replacements.

change interface of ResponseWithBody<S, T> to use <S extends number, T>

change interface of ResponseWithBody<S, T> to use <S extends number, T>

otherwise I am getting this errors:

Interface 'ResponseWithBody<S, T>' incorrectly extends interface 'Response'.
  Types of property 'status' are incompatible.
    Type 'S' is not assignable to type 'number'.

this is for typescript 3.5 and @types/superagent=4.1.1

[feature] immutable data structures

Generated mutable types:

interface Thing {
  name: string;
  children: Array<Thing>; 
}

type x = ResponseWithBody<200, Array<Thing>>;

Could be immutable types:

interface ReadonlyThing {
  readonly name: string;
  readonly children: ReadonlyArray<Thing>; 
}

type x = ReadonlyResponseWithBody<200, ReadonlyArray<ReadonlyThing>>;

This would be a breaking change, so maybe mutable types by default and opt-in to immutable types, by configuration flag.

Although my personal preference would be immutable by default.

Reason being is that I'm using functional programming paradigm, where immutable data-structures are preferred, to avoid accidental state mutation as a safety feature.

[BUG] Exception if there's a root path in spec

Just tried to integrate this library into my project and I just found a case where the library fails.

There is an issue with the getPathToMethodName function.

When I have a root path (/) in the paths object of the spec, the library crashes: "Cannot read property 'toUpperCase' of undefined".

It's caused by line 116, but originates from line above.

If the result variable is an empty string it throws.

I "fixed" it by doing this before calling the getTypescriptCode function:

if (spec.paths.hasOwnProperty('/')) {
    let prop = spec.paths['/'];
    delete spec.paths['/'];
    spec.paths['/index'] = prop;
}

This solution fixes the issue partially, because now the target path in the generated code is wrong.

The solution to the issue might be using an alias for the / path, like index for example.

[Feature] Non-Success Type Checking - Responses Union Type

Schema:

// ...
"responses": {
  "200": {
    "description": "A Thing.",
    "schema": {
      "$ref": "#/definitions/Thing"
    }
  },
  "400": {
    "description": "Invalid Thing Request.",
    "schema": {
      "type": "string"
    }
  },
  "404": {
    "description": "Thing not found.",
    "schema": {
      "type": "number"
    }
  }
}
// ...

Generates typescript response type of:

Promise < ResponseWithBody < ThingResponse >>

Expecting:

Promise < ResponseWithBody < 200ThingResponse | 400ThingResponse | 404ThingResponse >>

This allows for type checking of non-success responses as well as exhaustive pattern matching.

const unreachable = (n: never):any => n;

// pattern match on response type.
const poorMansPatternMatch = (response: ResponseWithBody < 200ThingResponse | 400ThingResponse | 404ThingResponse >): boolean =>
{
switch (response.type) {
   case 200:
      console.log(`Happy object: ${JSON.stringify(response.body)}`);
      return true;

   case 400:
   case 404:
      console.log(`Sad string/number: ${response.body}`);
      return false;

   default:
       unreachable(response.type); // compile time error, for unhandled response body types.
       console.warn(`Unhandled response type: ${response.type}`)
       return false;
}
}

Coding/File Guidelines

It would be nice if there was some general guidelines.

Coding Guidelines

Since there is prettier installed and pre-commit hook, direct guidelines are not required.

File Guidelines

Right now the file names are not following the same format everywhere, would be nice to keep it consistent.

GitHub Labels

It would be nice if there were labels related to code area.

(Support?) Type errors for dev environment & future plans

I'm looking for a good fork of wcandillon's work. This seems a good place to start off - especially since it's hosted by an Microsoft member.

Sadly, I'm required to have an URL-to-method lookup which may (probably) requires a small rewrite of this module. I'm also required to have properly used return types (partly true of #77).

Per readme, I've been trying to fire up the dev environment using npm run build:watch, which works, but I'm getting a ton of type errors.

At this point in time, I do not know if this is on a todo - wasn't able to find any hints on this.
I will be able to fix this, but I'd like to have this merged into here, rather than creating yet another fork that get's on npm.

In any case, I have to fix this nevertheless before implementing my wishes.
In case my feature requirements do not meet your opinion, I'd like to keep the core for the both of us the same (and putting my feature on-top).

Looking forward for clarification. Would love to contribute.

Package version not updated

Release version is 1.9.2, but version in package.json is still on 1.9.0, maybe due to changed release workflow w/ Travis CI?

(I'm not expired in these things, but there's at least "npm version", and more tools which even collect changelogs from git commits. What are you using/are you planning to use?)

API Proposal: Generate multiple files

Justification

Our API is going to be quite big and generating it all into one file will make the file very very large. I would like to avoid this, especially since a lot of the large sets will only be used on some specific pages (included admin pages).

Right now I don't commit the generated code to git, which is something that I would like to do in the future to allow us to follow code changes even if we can follow our swagger spec file.

API Proposal

Having a new way to generate code would be ideal in this situation. It would require a lot of changes to support, I can however see a good potential in being able to generate it per with the same ViewData.

let compiler = new Compiler({
  moduleName: "Test",
  className: "Test",
  swagger: swaggerSpec
});

compiler.compile("output_directory");

Something like that would generate a collection of files from the ViewData and resolve the import paths.

Considerations

  • Easier to maintain big projects
  • Performance improvements for big projects

Make the implementation follow the OpenAPI/Swagger spec for dictionaries

There are a few valid ways to define additionalProperties.

To define a dictionary, use type: object and use the additionalProperties keyword to specify the type of values in key/value pairs.

Instead of using an inline schema, additionalProperties can $ref another schema

If the dictionary values can be of any type (aka free-form object), use additionalProperties: true

https://swagger.io/docs/specification/data-models/dictionaries/

But might be best for the implementation to follow the OpenAPI/Swagger spec, and only allow for valid dictionary types.

Could maybe also handle some of these other invalid cases.

Originally posted by @scottc in #63 (comment)

[feature] decoder functions

In a perfect world, everyone would version their immutable apis and never introduce breaking changes.

But in reality co-workers could introduce breaking api changes.

There could potentially be a mismatch between the actual runtime json response and the static compile time typescript types.

This can cause runtime errors, but could be caught by the typechecker / developer at compile time.

So a good solution is to implement decoder functions at the boundaries of the application, which are run-time type checks, with some static types on top.

If the run-time type check fails, the endpoint could return an error, in the form of a boxed result type.

Some examples and helper libraries:

https://github.com/nvie/decoders
https://github.com/swissmanu/spicery
https://github.com/gcanti/io-ts
https://github.com/fabiandev/ts-runtime

version 3.0 ??

if (opts.swagger.swagger !== "2.0") {
throw new Error("Only Swagger 2 specs are supported");
}

1.9.0 is broken

Thanks for the great library, we are using it well in our projects.

Currently (v1.9.0) for the simplest case, the lintCode.js file is breaking generation. It seems as though it is attempting to lint the client as a javascript file instead of a typesript file. Here is a minimal reproduction of the error:

https://gist.github.com/andy-viv/8004ff39407f6d2fa14c8c4d14d36a2f

The error that occurs:

            throw new Error(`${error.reason} in ${error.evidence} (${error.code})`);
            ^

Error: Unexpected 'type'. in export type RequestHeaders = { (E024)
    at lint.errors.forEach (/Users/andrew.perlitch/repos/stg-test/node_modules/swagger-typescript-codegen/lib/enhance/lintCode.js:22:19)
    at Array.forEach (<anonymous>)
    at Object.lintCode (/Users/andrew.perlitch/repos/stg-test/node_modules/swagger-typescript-codegen/lib/enhance/lintCode.js:20:17)
    at Object.enhanceCode (/Users/andrew.perlitch/repos/stg-test/node_modules/swagger-typescript-codegen/lib/enhance/index.js:7:20)
    at Object.getTypescriptCode (/Users/andrew.perlitch/repos/stg-test/node_modules/swagger-typescript-codegen/lib/codegen.js:18:26)
    at Object.<anonymous> (/Users/andrew.perlitch/repos/stg-test/generate.js:6:28)
    at Module._compile (module.js:662:30)
    at Object.Module._extensions..js (module.js:673:10)
    at Module.load (module.js:575:32)
    at tryModuleLoad (module.js:515:12)

For now I am locking the version of swagger-typescript-codegen in my package.json to 1.8.1.

Are tests run on PR? I took the spec.json in the gist above directly from the test fixtures in this repo.

Also, I am noticing a strange discrepancy between npm versions and the releases on github. Perhaps check that you are tagging/releasing appropriately.

Regards

Response type not rendered when swagger responses is empty

I've found that if you have a swagger file where one or more of your operations has it's responses defined as an empty object, the generated api client returns Promise with no type, resulting in a TS error.

Example:

"/someoperation" : {
      "post" : {
        "operationId" : "SomeOperation",
        "consumes" : [ "application/json" ],
        "produces" : [ "application/json" ],
        "parameters" : [ ],
        "responses" : { },
     }
}

Result:

/**
 *
 * @method
 * @name ApiClient#SomeOperation
 */
SomeOperation(parameters: {} & CommonRequestOptions): Promise;

Typescript requires that promises have some type eg Promise.
In this situation the type should be voice i.e

SomeOperation(parameters: {} & CommonRequestOptions): Promise<void>;

Types with additionalProperties are not generated correctly

Hi, i just updated to version 2.0.0 and now my types with additionalProperties do not get generated correctly. Here is an example based on your tests for additionalProperties. Within the tests of swagger-typescript-codegen it seems to work, but in my project and my test project it doesn't. What am i doing wrong?

swagger.json:

{
  "swagger": "2.0",
  "info": {
    "version": "0.0.1",
    "title": "your title"
  },
  "paths": {
    "/persons": {
      "get": {
        "operationId": "get_person",
        "description": "Gets `Person` object.",
        "responses": {
          "200": {
            "description": "empty schema"
          }
        }
      }
    }
  },
  "definitions": {
    "some_def": {
      "type": "object",
      "properties": {
        "some_def": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "test_add_props_01": {
      "type": "object",
      "properties": {
        "some_prop": {
          "type": "string"
        }
      }
    },
    "test_add_props_02": {
      "type": "object",
      "properties": {
        "some_prop": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "test_add_props_03": {
      "type": "object",
      "properties": {
        "some_prop": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "test_add_props_04": {
      "type": "object",
      "properties": {
        "some_prop": {
          "type": "string"
        }
      },
      "additionalProperties": {
        "type": "string"
      }
    },
    "test_add_props_05": {
      "type": "object",
      "properties": {
        "some_prop": {
          "type": "string"
        }
      },
      "additionalProperties": {
        "type": "object",
        "properties": {
          "nested_prop": {
            "type": "string"
          }
        }
      }
    },
    "test_add_props_06": {
      "type": "object",
      "properties": {
        "some_prop": {
          "type": "string"
        }
      },
      "additionalProperties": {
        "$ref": "#/definitions/some_def"
      }
    },
    "test_add_props_07": {
      "type": "object"
    },
    "test_add_props_08": {
      "type": "object",
      "additionalProperties": false
    },
    "test_add_props_09": {
      "type": "object",
      "additionalProperties": true
    },
    "test_add_props_10": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "test_add_props_11": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "nested_prop": {
            "type": "string"
          }
        }
      }
    },
    "test_add_props_12": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/some_def"
      }
    }
  }
}

output.ts:

// tslint:disable

import * as request from "superagent";
import {
    SuperAgentStatic,
    SuperAgentRequest,
    Response
} from "superagent";

export type RequestHeaders = {
    [header: string]: string;
}
export type RequestHeadersHandler = (headers: RequestHeaders) => RequestHeaders;

export type ConfigureAgentHandler = (agent: SuperAgentStatic) => SuperAgentStatic;

export type ConfigureRequestHandler = (agent: SuperAgentRequest) => SuperAgentRequest;

export type CallbackHandler = (err: any, res ? : request.Response) => void;

export type some_def = {
    'some_def' ? : string;
};

export type test_add_props_01 = {
    'some_prop' ? : string;
};

export type test_add_props_02 = {
    'some_prop' ? : string;
};

export type test_add_props_03 = ;

export type test_add_props_04 = ;

export type test_add_props_05 = ;

export type test_add_props_06 = ;

export type test_add_props_07 = {};

export type test_add_props_08 = {};

export type test_add_props_09 = ;

export type test_add_props_10 = ;

export type test_add_props_11 = ;

export type test_add_props_12 = ;

export type Logger = {
    log: (line: string) => any
};

export interface ResponseWithBody < S extends number, T > extends Response {
    status: S;
    body: T;
}

export type QueryParameters = {
    [param: string]: any
};

export interface CommonRequestOptions {
    $queryParameters ? : QueryParameters;
    $domain ? : string;
    $path ? : string | ((path: string) => string);
    $retries ? : number; // number of retries; see: https://github.com/visionmedia/superagent/blob/master/docs/index.md#retrying-requests
    $timeout ? : number; // request timeout in milliseconds; see: https://github.com/visionmedia/superagent/blob/master/docs/index.md#timeouts
    $deadline ? : number; // request deadline in milliseconds; see: https://github.com/visionmedia/superagent/blob/master/docs/index.md#timeouts
}

/**
 * 
 * @class TestApi
 * @param {(string)} [domainOrOptions] - The project domain.
 */
export class TestApi {

    private domain: string = "";
    private errorHandlers: CallbackHandler[] = [];
    private requestHeadersHandler ? : RequestHeadersHandler;
    private configureAgentHandler ? : ConfigureAgentHandler;
    private configureRequestHandler ? : ConfigureRequestHandler;

    constructor(domain ? : string, private logger ? : Logger) {
        if (domain) {
            this.domain = domain;
        }
    }

    getDomain() {
        return this.domain;
    }

    addErrorHandler(handler: CallbackHandler) {
        this.errorHandlers.push(handler);
    }

    setRequestHeadersHandler(handler: RequestHeadersHandler) {
        this.requestHeadersHandler = handler;
    }

    setConfigureAgentHandler(handler: ConfigureAgentHandler) {
        this.configureAgentHandler = handler;
    }

    setConfigureRequestHandler(handler: ConfigureRequestHandler) {
        this.configureRequestHandler = handler;
    }

    private request(method: string, url: string, body: any, headers: RequestHeaders, queryParameters: QueryParameters, form: any, reject: CallbackHandler, resolve: CallbackHandler, opts: CommonRequestOptions) {
        if (this.logger) {
            this.logger.log(`Call ${method} ${url}`);
        }

        const agent = this.configureAgentHandler ?
            this.configureAgentHandler(request.default) :
            request.default;

        let req = agent(method, url);
        if (this.configureRequestHandler) {
            req = this.configureRequestHandler(req);
        }

        req = req.query(queryParameters);

        if (body) {
            req.send(body);

            if (typeof(body) === 'object' && !(body.constructor.name === 'Buffer')) {
                headers['Content-Type'] = 'application/json';
            }
        }

        if (Object.keys(form).length > 0) {
            req.type('form');
            req.send(form);
        }

        if (this.requestHeadersHandler) {
            headers = this.requestHeadersHandler({
                ...headers
            });
        }

        req.set(headers);

        if (opts.$retries && opts.$retries > 0) {
            req.retry(opts.$retries);
        }

        if (opts.$timeout && opts.$timeout > 0 || opts.$deadline && opts.$deadline > 0) {
            req.timeout({
                deadline: opts.$deadline,
                response: opts.$timeout
            });
        }

        req.end((error, response) => {
            // an error will also be emitted for a 4xx and 5xx status code
            // the error object will then have error.status and error.response fields
            // see superagent error handling: https://github.com/visionmedia/superagent/blob/master/docs/index.md#error-handling
            if (error) {
                reject(error);
                this.errorHandlers.forEach(handler => handler(error));
            } else {
                resolve(response);
            }
        });
    }

    get_personURL(parameters: {} & CommonRequestOptions): string {
        let queryParameters: QueryParameters = {};
        const domain = parameters.$domain ? parameters.$domain : this.domain;
        let path = '/persons';
        if (parameters.$path) {
            path = (typeof(parameters.$path) === 'function') ? parameters.$path(path) : parameters.$path;
        }

        if (parameters.$queryParameters) {
            queryParameters = {
                ...queryParameters,
                ...parameters.$queryParameters
            };
        }

        let keys = Object.keys(queryParameters);
        return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '');
    }

    /**
     * Gets `Person` object.
     * @method
     * @name TestApi#get_person
     */
    get_person(parameters: {} & CommonRequestOptions): Promise < ResponseWithBody < 200, void >> {
        const domain = parameters.$domain ? parameters.$domain : this.domain;
        let path = '/persons';
        if (parameters.$path) {
            path = (typeof(parameters.$path) === 'function') ? parameters.$path(path) : parameters.$path;
        }

        let body: any;
        let queryParameters: QueryParameters = {};
        let headers: RequestHeaders = {};
        let form: any = {};
        return new Promise((resolve, reject) => {

            if (parameters.$queryParameters) {
                queryParameters = {
                    ...queryParameters,
                    ...parameters.$queryParameters
                };
            }

            this.request('GET', domain + path, body, headers, queryParameters, form, reject, resolve, parameters);
        });
    }

}

export default TestApi;

date-time format field is generated as string type

Suppose we have a Date query param

@Get()
getNextDate(@Query('date') date: Date) { .. }

A generated swagger parameter definition for query param would be

"parameters": [
	{
		"in": "query",
		"name": "",
		"required": true,
		"format": "date-time",
		"type": "string"
	}
]

But swagger-typescript-codegen would type it as string

GetNextDate(parameters: {
        'date': string,
    } & CommonRequestOptions)

And when try to use it with Date, TS error would be raised Type 'Date' is not assignable to type 'string'
e.g.

const date:Date =  new Date();
const res = await cl.GetDate({date: date});

CVE-2021-33502 in normalize-url

CVE-2021-33502 exists in normalize 4.5.0:

"normalize-url": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ=="
},

Patch exists in 6.0.1, 5.3.1, 4.5.1.

Dependency path:

  • swagger-typescript-codegen
  • update-notifier
  • latest-version
  • package-json
  • got
  • cacheable-request --> normalize-url

The 4.5.1 patch is compatible

"normalize-url": "^4.1.0",

This should be a straight forward fix

Allow deprecated methods to be processed

At the moment, codegen does not support generating client endpoints for deprecated methods. However, I have a use case where I'd need that specific functionality.

I've been thinking that it should be fairly straight forward to add a configuration option for processing deprecated methods (off by default, for backwards compatibility). What do you think, does this sound like an idea? I'd be happy to implement it.

Kind regards,
Andreas

Query parameters in POST request are converted to formdata

It looks like it's not possible to have query parameters on POST requests, they are converted to formdata here: https://github.com/mtennoe/swagger-typescript-codegen/blob/master/templates/method.mustache#L179

Is there a specific reason this conversion is done? In our usecase, we generate a swagger spec from proto/grpc definitions using grpc-gateway, where query parameters are used to map fields in a Create request that aren't part of the actual resource to create: https://cloud.google.com/apis/design/standard_methods#create. When these fields are added as formdata in the request they are ignored when handled by the grpc-gateway.

It would be nice if there's a way to disable this conversion to formdata

Version 1.9.7 not packaged correctly

Hi again!

It seems the npm package of version 1.9.7 is not quite up to date. Looking at a diff between npm packages for 1.9.6 and 1.9.7 I see that package.json is updated, and the allOf.json test spec is included, but the changes to object.js mapper are not there.

Perhaps there was some issue when publishing?

Kind regards,
Andreas

[question] Webpack compilation errors

Hi,

first of all, thank you for maintaining this repo. I've recently started using this tool in my Nuxt Typescript project and I am getting errors during compilation in options.d.ts file

ERROR in /home/ondra/Projects/cluster/endevel/endcode/src/end/services/cars/front/node_modules/swagger-typescript-codegen/lib/options/options.d.ts                              
1:23 Cannot find type definition file for 'js-beautify'.

ERROR in /home/ondra/Projects/cluster/endevel/endcode/src/end/services/cars/front/node_modules/swagger-typescript-codegen/lib/options/options.d.ts                 
18:31 Cannot find name 'JsBeautifyOptions'.

After hours of searching I was unable to resolve the issue (unless I simple comment out errored lines) - I am wondering if someone has similar issue...

Maybe there is some specific webpack/Nuxt config needed... do you have any experience with this kind of issue?

Changelog?

Is there a changelog somewhere? We're currently on 1.10.0 and it would be neat to upgrade, but I'd wanna see what has changed/improved/gotten deprecated obviously ๐Ÿ™‚

[TS Error]: AngularJS + Typescript 2.5.2 + Swagger TS code generation error while importing

Description

Hi there,

I filed the same bug here: swagger-api/swagger-codegen#9328
but I am facing a different set of issues with this swagger codegen version.

The following errors happen when I try to compile the generated TS client file.

dist/otrBackendService.ts(80,16): error TS1127: Invalid character.
dist/otrBackendService.ts(80,32): error TS1127: Invalid character.
dist/otrBackendService.ts(80,34): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(81,9): error TS1005: ',' expected.
dist/otrBackendService.ts(81,18): error TS1005: ';' expected.
dist/otrBackendService.ts(136,20): error TS1127: Invalid character.
dist/otrBackendService.ts(136,36): error TS1127: Invalid character.
dist/otrBackendService.ts(136,38): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(137,9): error TS1005: ',' expected.
dist/otrBackendService.ts(137,18): error TS1005: ';' expected.
dist/otrBackendService.ts(618,16): error TS1127: Invalid character.
dist/otrBackendService.ts(618,36): error TS1127: Invalid character.
dist/otrBackendService.ts(618,55): error TS1127: Invalid character.
dist/otrBackendService.ts(618,56): error TS1127: Invalid character.
dist/otrBackendService.ts(618,58): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(619,9): error TS1005: ',' expected.
dist/otrBackendService.ts(619,18): error TS1005: ';' expected.
dist/otrBackendService.ts(1109,16): error TS1127: Invalid character.
dist/otrBackendService.ts(1109,32): error TS1127: Invalid character.
dist/otrBackendService.ts(1109,34): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(1110,9): error TS1005: ',' expected.
dist/otrBackendService.ts(1110,18): error TS1005: ';' expected.
dist/otrBackendService.ts(1128,34): error TS1127: Invalid character.
dist/otrBackendService.ts(1128,36): error TS1131: Property or signature expected.
dist/otrBackendService.ts(1128,53): error TS1127: Invalid character.
dist/otrBackendService.ts(1129,5): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(1130,26): error TS1109: Expression expected.
dist/otrBackendService.ts(1131,1): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(1162,20): error TS1127: Invalid character.
dist/otrBackendService.ts(1162,36): error TS1127: Invalid character.
dist/otrBackendService.ts(1162,38): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(1163,9): error TS1005: ',' expected.
dist/otrBackendService.ts(1163,18): error TS1005: ';' expected.
dist/otrBackendService.ts(1339,16): error TS1127: Invalid character.
dist/otrBackendService.ts(1339,29): error TS1127: Invalid character.
dist/otrBackendService.ts(1339,31): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(1340,9): error TS1005: ',' expected.
dist/otrBackendService.ts(1340,18): error TS1005: ';' expected.
dist/otrBackendService.ts(1653,32): error TS1127: Invalid character.
dist/otrBackendService.ts(1654,5): error TS1131: Property or signature expected.
dist/otrBackendService.ts(1654,11): error TS1127: Invalid character.
dist/otrBackendService.ts(1654,13): error TS1109: Expression expected.
dist/otrBackendService.ts(1655,5): error TS1109: Expression expected.
dist/otrBackendService.ts(1656,1): error TS1128: Declaration or statement expected.
dist/otrBackendService.ts(1865,23): error TS1127: Invalid character.
dist/otrBackendService.ts(1865,42): error TS1127: Invalid character.
dist/otrBackendService.ts(1865,44): error TS1128: Declaration or statement expected

Swagger-codegen version

1.9.5

Swagger declaration file content or url

Swagger JSON file used to generate TS client code. The JSON file should be fine.
https://otr-backend-service-us-devo.offtherecord.com/v2/api-docs

gulp task used for generation

....
gulp.task('angular-codegen', function(done){

var CodeGen = require('swagger-typescript-codegen').CodeGen;
var dest = 'dist';
apis.forEach(function(api){
    var swagger = JSON.parse(fs.readFileSync(api.swagger, 'utf-8'));
    var source = CodeGen.getTypescriptCode({ moduleName: api.moduleName, className: api.className, swagger: swagger });
    gutil.log('Generated ' + api.moduleName + '.js from ' + api.swagger);

    var generatedApiFile = dest + '/' + api.moduleName + '.ts';
    fs.writeFileSync(generatedApiFile, source, 'UTF-8');

    gulp.src([generatedApiFile]) //otherSources])
        .pipe(gulp.dest(dest))
        .pipe(notify("File has been successfully generated!"));
});
done();

});

Steps to reproduce

tsc --project .tsconfig

TSC Version

tsc --version
Version 2.5.2

.tsconfig file

{
"compilerOptions": {
"module": "CommonJS",
"target": "es5",
"experimentalDecorators": true
},
"include": [
"./public/app/"
]
}

Question

Is there a version of TS that supports compilation of this files because perhaps the swagger codegen was generating TS code that was compliant against certain versions of the TS compiler? If not, how do we solve this?

Enable prettier

Prettier should be run on precommit to ensure consistent styling

API Proposal: Support other template languages

Justification

Right now only Mustache is supported, I can see the benefits of the template language. It's just a little bit off putting for people how doesn't know it that well to build custom templates.

I don't consider this important, just would like to open a discussion around it.

API Proposal

There are already a something building on top of this, building this up more to be able to handle more abstract types would make it easy to solve.

https://github.com/mtennoe/swagger-typescript-codegen/blob/master/src/transform/transformToCodeWithMustache.ts#L12-L38

I am not sure what the design reason behind having the default templates inside the transform code, it would be nice to move that out of there.
https://github.com/mtennoe/swagger-typescript-codegen/blob/master/src/transform/transformToCodeWithMustache.ts#L40-L52

Considerations

  • Easier to maintain.
  • Easier for new people.

Update the security handling in getViewFromSwagger2

There is some seemingly weird things going on around the securityDefinitions and the security related properties on the methods.

We should figure out what these are actually supposed to do and refactor the code to be easier to understand.

Types are missing JSDocs

The api methods have docs, but the types themselves do not.

Actual:
Response types are missing JSDocs

export type User {
    id: number;
    username: string;
}

Expected:
JSDocs containing the definition descriptions.

/** */
export type User {
    /** {integer} The user ID. */
    id: number;
    /** The user name. */
    username: string;
}

Spec:
https://swagger.io/docs/specification/2-0/describing-responses/

definitions:
  User:
    type: object
    properties:
      id:
        type: integer
        description: The user ID.
      username:
        type: string
        description: The user name.

Is there support for swagger 3+?

Hi there! I am looking for swagger codeine solution for my angular app and found your package... But when I started to try it I got error that Only Swagger 2 specs are supported... Why is it so? Should I hope to get also Swagger 3 support in this lib? Or maybe have I missed some configuration?

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.