Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { {{configurationClassName}} } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand Down Expand Up @@ -26,12 +26,14 @@ export class {{apiModuleClassName}} {
};
}

constructor( @Optional() @SkipSelf() parentModule: {{apiModuleClassName}},
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: {{apiModuleClassName}} | null = inject({{apiModuleClassName}}, { optional: true, skipSelf: true });
private http: HttpClient | null = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('{{apiModuleClassName}} is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{>licenseInfo}}
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When ngVersion is 9–13, this unconditional inject import makes the generated client fail to compile even though those Angular versions remain supported. Gate the functional-injection template on the minimum Angular version that provides inject, or raise the generator’s supported minimum.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache, line 4:

<comment>When `ngVersion` is 9–13, this unconditional `inject` import makes the generated client fail to compile even though those Angular versions remain supported. Gate the functional-injection template on the minimum Angular version that provides `inject`, or raise the generator’s supported minimum.</comment>

<file context>
@@ -1,7 +1,7 @@
 /* tslint:disable:no-unused-variable member-ordering */
 
-import { Inject, Injectable, Optional }                      from '@angular/core';
+import { inject, Injectable }                      from '@angular/core';
 import { HttpClient, HttpHeaders, HttpParams,
          HttpResponse, HttpEvent{{#httpContextInOptions}}, HttpContext {{/httpContextInOptions}}
</file context>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this would break backwards compatibility, so i guess we should avoid that until we officially drop support for ng < 14

import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent{{#httpContextInOptions}}, HttpContext {{/httpContextInOptions}}
} from '@angular/common/http';
Expand Down Expand Up @@ -62,8 +62,13 @@ export class {{classname}} extends BaseService implements {{classname}}Interface
export class {{classname}} extends BaseService {
{{/withInterfaces}}

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: {{configurationClassName}}) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Consumers that instantiate a generated service directly now get Expected 0 arguments and cannot construct it outside Angular DI because the field initializer calls inject. Preserve a backwards-compatible construction path, or update the generator’s supported public usage and all repository consumers together.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache, line 67:

<comment>Consumers that instantiate a generated service directly now get `Expected 0 arguments` and cannot construct it outside Angular DI because the field initializer calls `inject`. Preserve a backwards-compatible construction path, or update the generator’s supported public usage and all repository consumers together.</comment>

<file context>
@@ -62,8 +62,13 @@ export class {{classname}} extends BaseService implements {{classname}}Interface
-        super(basePath, configuration);
+    protected httpClient: HttpClient = inject(HttpClient);
+
+    constructor() {
+        super(
+          inject(BASE_PATH, { optional: true }) ?? undefined,
</file context>

super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject({{configurationClassName}}, { optional: true }) ?? undefined
);
}

{{#operation}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { Configuration } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand All @@ -17,12 +17,14 @@ export class ApiModule {
};
}

constructor( @Optional() @SkipSelf() parentModule: ApiModule,
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });
private http: HttpClient = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -33,8 +33,13 @@ import { BaseService } from '../api.base.service';
})
export class DefaultService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { Configuration } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand All @@ -17,12 +17,14 @@ export class ApiModule {
};
}

constructor( @Optional() @SkipSelf() parentModule: ApiModule,
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });
private http: HttpClient = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -33,8 +33,13 @@ import { BaseService } from '../api.base.service';
})
export class DefaultService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { Configuration } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand All @@ -17,12 +17,14 @@ export class ApiModule {
};
}

constructor( @Optional() @SkipSelf() parentModule: ApiModule,
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });
private http: HttpClient = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -33,8 +33,13 @@ import { BaseService } from '../api.base.service';
})
export class DefaultService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { Configuration } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand All @@ -17,12 +17,14 @@ export class ApiModule {
};
}

constructor( @Optional() @SkipSelf() parentModule: ApiModule,
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });
private http: HttpClient = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -31,8 +31,13 @@ import { BaseService } from '../api.base.service';
})
export class PetService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { Configuration } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand All @@ -17,12 +17,14 @@ export class ApiModule {
};
}

constructor( @Optional() @SkipSelf() parentModule: ApiModule,
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The template now emits inject() in class field initializers unconditionally, but the generator still documents support down to Angular 9.0.0. inject is only exported from @angular/core starting in Angular 14.0, and field-initializer inject() requires Angular 14.2+. Any user generating with ngVersion < 14.2 gets code that fails to compile (no inject export) or throws NG0203 at runtime. Gate this new pattern behind an ngVersionAtLeast_14 (or 14.2) conditional in api.module.mustache and keep the legacy @Optional()/@SkipSelf() decorator path for older versions, or update the documented minimum supported ngVersion.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/typescript-angular/builds/composed-schemas/api.module.ts, line 20:

<comment>The template now emits `inject()` in class field initializers unconditionally, but the generator still documents support down to Angular 9.0.0. `inject` is only exported from `@angular/core` starting in Angular 14.0, and field-initializer `inject()` requires Angular 14.2+. Any user generating with ngVersion < 14.2 gets code that fails to compile (no `inject` export) or throws NG0203 at runtime. Gate this new pattern behind an `ngVersionAtLeast_14` (or 14.2) conditional in api.module.mustache and keep the legacy `@Optional()/@SkipSelf()` decorator path for older versions, or update the documented minimum supported ngVersion.</comment>

<file context>
@@ -17,12 +17,14 @@ export class ApiModule {
-    constructor( @Optional() @SkipSelf() parentModule: ApiModule,
-                 @Optional() http: HttpClient) {
-        if (parentModule) {
+    private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });
+    private http: HttpClient = inject(HttpClient, { optional: true });
+
</file context>

private http: HttpClient = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -31,8 +31,13 @@ import { BaseService } from '../api.base.service';
})
export class PetService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NgModule, ModuleWithProviders, SkipSelf, Optional } from '@angular/core';
import { NgModule, ModuleWithProviders, inject } from '@angular/core';
import { Configuration } from './configuration';
import { HttpClient } from '@angular/common/http';

Expand All @@ -17,12 +17,14 @@ export class ApiModule {
};
}

constructor( @Optional() @SkipSelf() parentModule: ApiModule,
@Optional() http: HttpClient) {
if (parentModule) {
private parentModule: ApiModule = inject(ApiModule, { optional: true, skipSelf: true });
private http: HttpClient = inject(HttpClient, { optional: true });

constructor() {
if (this.parentModule) {
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
}
if (!http) {
if (!this.http) {
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
'See also https://github.com/angular/angular/issues/20575');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -33,8 +33,13 @@ import { BaseService } from '../api.base.service';
})
export class PetService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -31,8 +31,13 @@ import { BaseService } from '../api.base.service';
})
export class StoreService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpContext
} from '@angular/common/http';
Expand All @@ -31,8 +31,13 @@ import { BaseService } from '../api.base.service';
})
export class UserService extends BaseService {

constructor(protected httpClient: HttpClient, @Optional() @Inject(BASE_PATH) basePath: string|string[], @Optional() configuration?: Configuration) {
super(basePath, configuration);
protected httpClient: HttpClient = inject(HttpClient);

constructor() {
super(
inject(BASE_PATH, { optional: true }) ?? undefined,
inject(Configuration, { optional: true }) ?? undefined
);
}

/**
Expand Down
Loading
Loading