Skip to content

SwaggerToTypeScriptClientGenerator

JonasSchmiddunser-AraCom edited this page Sep 16, 2020 · 138 revisions

Inherits from ClientGeneratorBase

The following code generates the TypeScript client code and DTO classes for a given Swagger specification:

var document = SwaggerDocument.FromUrl(swaggerSpecUrl);

var settings = new SwaggerToTypeScriptClientGeneratorSettings
{
	ClassName = "{controller}Client",
};

var generator = new SwaggerToTypeScriptClientGenerator(document, settings);
var code = generator.GenerateFile();

Output

Available framework/library templates

The used template can be set via the Template property of the SwaggerToTypeScriptClientGeneratorSettings class.

JQueryCallbacks

Generates client classes which use JQuery for HTTP handling and simple callbacks for success and error handling.

JQueryPromises

Generates client classes which use JQuery for HTTP handling and JavaScript Promises to handle asynchronicity. Most modern browsers only support JavaScript ES5 which does not provide a native Promise implementation. You can choose from two promise types via the PromiseType setting:

AngularJS

Generates an AngularJS service class which uses the AngularJS http service.

Angular

The Angular template generates an Angular 2 service to access your backend.

More information about the Angular template

Fetch

Warning: TypeScript v2.6.0 and v2.6.1 have a broken HeadersInit declaration, please use v2.6.2+ or earlier versions.

Template for the official window.fetch API with promises.

Required method on base class for UseTransformResultMethod:

transformResult(url: string, response: Response, processor: (response: Response) => Promise<any>): Promise<any> { 
    return processor(response);
}

Aurelia (based on Fetch)

Template for Aurelia using the HttpClient from aurelia-fetch-client. By using the HttpClient via dependency injection you can add global interceptors and other global configurations. When using a global response interceptor, beware that the generated TypeScript code calls the text() method to read the response. Because the response of a fetch call can only be read once, you cannot call arrayBuffer(), blob(), json(), text() or formData() on the response object yourself or the generated TypeScript code will throw an exception. If you need to read the response in your interceptor, you should clone the response first and perform the text() function or equivalent on the cloned Response (like this: response.clone().text()).

Sample project

Datetime handling

  • When generating DTO classes instead of interfaces, datetime values are automatically converted into a Date or MomentJS moment object.

TimeSpan handling

  • When generating DTO classes instead of interfaces, TimeSpan values are automatically converted into a Date or MomentJS moment.Duration object. See Moment Durations.

    • A TimeSpan coming from a .Net Web API is formatted as string with the following format day.hours:minutes.seconds.milliseconds (ex: 7.23:59:59) in json. This format can be passed to moment.duration without change.
    • To send a moment.Duration back to the Web API we need to format it in the same manner again. But this isn't support by MomentJS and a plugin needs to be added. The import for this plugin has been added to NSwag generated TypeScript code. See import 'moment-duration-format';.

    Use the following script to install the plugin.

    npm install moment-duration-format
    npm install --save-dev @types/moment-duration-format
    

Extended classes and extension code

It is possible to extend the generated classes with own code. With this mechanism, you can add specific security code, caching or additional headers, new methods or properties. This works for client classes as well as the DTO classes. The external code is specified with the "ExtensionCode" setting. It accepts source code or a path to a .ts file (recommended).

Related Settings:

  • TypeScriptGeneratorSettings.ExtensionCode: The external code
  • TypeScriptGeneratorSettings.ExtendedClasses (requires extension code): The names of the extended classes
  • BaseClass (requires extension code): The base class of all generated client classes

Check out the NJsonSchema documentation for more information.

Extension code variables

In the ExtensionCode you can use the {clientClasses} variable which generates a mapping dictionary for all generated client classes. The output will look like:

{"PersonController": PersonController, "CompanyController": CompanyController}

When using the AngularJS template you can use this variable to register all generated client classes as AngularJS services. To do so, add the following code to your ExtensionCode:

var clientClasses = {clientClasses};
for (var clientClass in clientClasses) {
    if (clientClasses.hasOwnProperty(clientClass)) {
        angular.module('app').service(clientClass, ['$http', clientClasses[clientClass]]);
    } 
}

Extend client classes

You can extend generated classes by adding class names to the ExtendedClasses setting. The bodies of the extended classes are then copied into the generated classes. The external code can be defined in the "ExtensionCode" setting (the import of the generated classes must look as follows):

// Sample template: Angular2

import * as generated from "./apiClients";

class PersonsClient extends generated.PersonsClient {
    public myNewMethod() {

    }
}

Transform the options or the result

You can customize the HTTP options or process each HTTP response. Use the settings "UseTransformOptionsMethod" or "UseTransformResultMethod" to enable the features. The then required "transformOptions" or "transformResult" methods can be implemented per client class ("ExtendedClasses" setting) or as a base class for all clients ("BaseClass" setting). The externally implemented "transformOptions(options)" method must return a promise which resolves to the transformed options (except for the JQuery templates, they require sync methods). The method parameters depend on the selected generator template (i.e. the used framework/library).

A sample for Angular 2 (the "BaseClass" setting is set to "ClientBase"):

// Sample template: Angular2

import * as generated from "./serviceClients";
import { RequestOptionsArgs } from '@angular/http'; // ignore

export class ClientBase {
    protected transformOptions(options: RequestOptionsArgs) {
        // TODO: Change options if required

        console.log("HTTP call, options: " + JSON.stringify(options));

        options.headers.append("myheader", "myvalue"); 
        return Promise.resolve(options);
    }

    protected transformResult(url: string, response: Response, processor: (response: Response) => any) {
        // TODO: Return own result or throw exception to change default processing behavior, 
        // or call processor function to run the default processing logic

        console.log("Service call: " + url);
        return processor(response); 
    }
}

Add a custom JSON.parse() reviver function

The Angular2, Fetch and Aurelia templates generate a protected jsonParseReviver field which is passed to all JSON.parse() calls. This reviver field can only be set with an extension class. To do so, add your client class to the ExtensionClasses array setting and implement the following ExtensionCode (sample for the Fetch template):

class GeoClient extends generated.GeoClientBase {
    constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
        super(baseUrl, http);

        this.jsonParseReviver = (key: string, value: any) => {
            return value; // TODO: Transform value if necessary
        };
    }
}