Skip to content

[typescript-angular] generated package/ApiModule is not AOT-compatible #6722

Description

@JohannesHoppe
Description

Angular-Typescript code does break the AOT compilation of the consuming app. AOT compilation is going to be the default in near future.
I tested the generated code together with angular-cli 1.4.4 and angular 4.4.5.

ng serve is now complaining the following:

ERROR in Error: Error encountered resolving symbol values statically.
Calling function 'ApiModule', function calls are not supported.
Consider replacing the function or lambda with a reference to an exported function....
Swagger-codegen version

v3.0.0-20171009.075709-6 (snapshot) but also applies to v2.3.0

Command line used for generation

So I created an angular-typescript client (3.0.0-branch) with the following config:

{
  "npmName": "my-client-package",
  "npmVersion": "0.0.1",
  "snapshot": true,
  "ngVersion": "4.4.5"
}
java -jar swagger-codegen-cli.jar generate -i http://localhost:5000/swagger/v1/swagger.json -l typescript-angular -c config.json -o client-ts/
cd client-ts
npm pack
Steps to reproduce

Install the package via npm install my-client-package to a fresh Angular-CLI application.
Include the generated module:

export function getApiConfig() {
  return new Configuration({
    basePath:  environment.API_BASE_PATH ,
  });
}

@NgModule({
  
  imports: [
    ApiModule.forConfig(getApiConfig)
  ]
})
export class AppModule { }
Suggest a fix/enhancement

switch from tsc to ngc
see this:

Long story short: tsc is not enough. Code must be generated via ngc so that the package has metadata. If there is no metadata, the NgModule can't be included, and the compiler rejects with a misleading message. In a perfect world the result conforms to the Angular Package Format v4.0, too.
See http://blog.mgechev.com/2017/01/21/distributing-an-angular-library-aot-ngc-types/ for an introduction to the topic.

Current workaround

Don't use the generated @NgModule. Copy its content into the application, e.g:

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { Configuration, MyService } from 'my-client-package';

/*
 * Workaround that replaces the ApiModule from  'my-client-package'
 * --> makes code AOT-compatible again
 *
 * Reason:
 * tsc does not generate *.metadata.json which breaks compatibility with angular’s AOT compiler
 *
 * avoids:
 * ERROR in Error: Error encountered resolving symbol values statically.
 * Calling function 'ApiModule', function calls are not supported.
 * Consider replacing the function or lambda with a reference to an exported function
 */
@NgModule({
  imports:      [ CommonModule, HttpClientModule ],
  declarations: [],
  exports:      [],
  providers:    [ MyService ]
})
export class ApiWorkaroundModule {
    public static forConfig(configurationFactory: () => Configuration): ModuleWithProviders {
        return {
            ngModule: ApiWorkaroundModule,
            providers: [ {provide: Configuration, useFactory: configurationFactory}]
        };
    }
}

Now you can use:

  imports: [
    ApiWorkaroundModule.forConfig(getApiConfig)
  ]

Code compiles again, since ApiWorkaroundModule is now a part of the main compilation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions