From 3a8800eb4192b83bcb43058626b2636c68ac2357 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Thu, 21 Nov 2024 16:39:22 +0100 Subject: [PATCH 1/5] refactor: remove requestParameters destructuration --- .../typescript-nestjs/api.service.mustache | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache index d33a206803f7..9fd95ba87f3f 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache @@ -102,23 +102,13 @@ export class {{classname}} { public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable>; public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable { {{/useSingleRequestParameter}} -{{#allParams.0}} -{{#useSingleRequestParameter}} - const { - {{#allParams}} - {{paramName}}, - {{/allParams}} - } = requestParameters; - -{{/useSingleRequestParameter}} -{{/allParams.0}} {{#allParams}} {{#required}} {{#isConstEnumParam}} let {{paramName}} = {{{dataType}}}; {{/isConstEnumParam}} {{^isConstEnumParam}} - if ({{paramName}} === null || {{paramName}} === undefined) { + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} === null || {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} === undefined) { throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.'); } @@ -129,24 +119,24 @@ export class {{classname}} { let queryParameters = new URLSearchParams(); {{#queryParams}} {{#isArray}} - if ({{paramName}}) { + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) { {{#isCollectionFormatMulti}} - {{paramName}}.forEach((element) => { + {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.forEach((element) => { queryParameters.append('{{baseName}}', element); }) {{/isCollectionFormatMulti}} {{^isCollectionFormatMulti}} - queryParameters['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); + queryParameters['{{baseName}}'] = {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); {{/isCollectionFormatMulti}} } {{/isArray}} {{^isArray}} - if ({{paramName}} !== undefined && {{paramName}} !== null) { + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined && {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== null) { {{#isDateTime}} - queryParameters.append('{{baseName}}', ({{paramName}}).toISOString()); + queryParameters.append('{{baseName}}', ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}).toISOString()); {{/isDateTime}} {{^isDateTime}} - queryParameters.append('{{baseName}}', {{paramName}}); + queryParameters.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}); {{/isDateTime}} } {{/isArray}} @@ -156,13 +146,13 @@ export class {{classname}} { let headers = {...this.defaultHeaders}; {{#headerParams}} {{#isArray}} - if ({{paramName}}) { - headers['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) { + headers['{{baseName}}'] = {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); } {{/isArray}} {{^isArray}} - if ({{paramName}} !== undefined && {{paramName}} !== null) { - headers['{{baseName}}'] = String({{paramName}}); + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined && {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== null) { + headers['{{baseName}}'] = String({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}); } {{/isArray}} {{/headerParams}} @@ -256,20 +246,20 @@ export class {{classname}} { {{#formParams}} {{#isArray}} - if ({{paramName}}) { + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) { {{#isCollectionFormatMulti}} - {{paramName}}.forEach((element) => { + {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.forEach((element) => { formParams!.append('{{baseName}}', element); }) {{/isCollectionFormatMulti}} {{^isCollectionFormatMulti}} - formParams!.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])); + formParams!.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])); {{/isCollectionFormatMulti}} } {{/isArray}} {{^isArray}} - if ({{paramName}} !== undefined) { - formParams!.append('{{baseName}}', {{paramName}}); + if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined) { + formParams!.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}); } {{/isArray}} {{/formParams}} @@ -282,7 +272,7 @@ export class {{classname}} { } return this.httpClient.{{httpMethod}}{{^isResponseFile}}<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>{{/isResponseFile}}(`${this.basePath}{{{path}}}`,{{#isBodyAllowed}} - {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}} + {{#bodyParam}}{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}} { {{#hasQueryParams}} params: queryParameters, From 9d9259eae4f5a704335cf5ffba5be9c3a4faa230 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Thu, 21 Nov 2024 17:51:34 +0100 Subject: [PATCH 2/5] feat: add reserved param names sample --- ...ypescript-nestjs-reserved-param-names.yaml | 6 + .../reserved-param-names.yaml | 37 ++++ .../builds/reservedParamNames/.gitignore | 4 + .../.openapi-generator-ignore | 23 +++ .../.openapi-generator/FILES | 10 ++ .../.openapi-generator/VERSION | 1 + .../builds/reservedParamNames/README.md | 162 ++++++++++++++++++ .../builds/reservedParamNames/api.module.ts | 70 ++++++++ .../builds/reservedParamNames/api/api.ts | 3 + .../reservedParamNames/api/default.service.ts | 127 ++++++++++++++ .../reservedParamNames/configuration.ts | 109 ++++++++++++ .../builds/reservedParamNames/git_push.sh | 57 ++++++ .../builds/reservedParamNames/index.ts | 4 + .../builds/reservedParamNames/model/models.ts | 0 .../builds/reservedParamNames/variables.ts | 7 + 15 files changed, 620 insertions(+) create mode 100644 bin/configs/typescript-nestjs-reserved-param-names.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.gitignore create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator-ignore create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/FILES create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/VERSION create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/README.md create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api.module.ts create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/api.ts create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/configuration.ts create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/git_push.sh create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/index.ts create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/model/models.ts create mode 100644 samples/client/petstore/typescript-nestjs/builds/reservedParamNames/variables.ts diff --git a/bin/configs/typescript-nestjs-reserved-param-names.yaml b/bin/configs/typescript-nestjs-reserved-param-names.yaml new file mode 100644 index 000000000000..c80064785d3e --- /dev/null +++ b/bin/configs/typescript-nestjs-reserved-param-names.yaml @@ -0,0 +1,6 @@ +generatorName: typescript-nestjs +outputDir: samples/client/petstore/typescript-nestjs/builds/reservedParamNames +inputSpec: modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml +templateDir: modules/openapi-generator/src/main/resources/typescript-nestjs +additionalProperties: + "useSingleRequestParameter" : true diff --git a/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml b/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml new file mode 100644 index 000000000000..91f3b8588afc --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml @@ -0,0 +1,37 @@ +openapi: 3.0.0 +info: + description: Test reserved param names + version: 1.0.0 + title: Reserved param names +paths: + /test: + post: + security: + - bearerAuth: [] + summary: Test reserved param names + description: '' + operationId: testReservedParamNames + parameters: + - name: from + in: query + description: Might conflict with rxjs import + required: true + schema: + type: string + - name: headers + in: header + description: Might conflict with headers const + required: true + schema: + type: string + responses: + '200': + description: successful operation + '405': + description: Invalid input +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.gitignore b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.gitignore new file mode 100644 index 000000000000..149b57654723 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator-ignore b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/FILES b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/FILES new file mode 100644 index 000000000000..229c09ab6277 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/FILES @@ -0,0 +1,10 @@ +.gitignore +README.md +api.module.ts +api/api.ts +api/default.service.ts +configuration.ts +git_push.sh +index.ts +model/models.ts +variables.ts diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/VERSION b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/VERSION new file mode 100644 index 000000000000..884119126398 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.11.0-SNAPSHOT diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/README.md b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/README.md new file mode 100644 index 000000000000..0cc526067ed1 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/README.md @@ -0,0 +1,162 @@ +## @ + +### Building + +To install the required dependencies and to build the typescript sources run: +``` +npm install +npm run build +``` + +#### General usage + +In your Nestjs project: + + +``` +// without configuring providers +import { ApiModule } from ''; +import { HttpModule } from '@nestjs/axios'; + +@Module({ + imports: [ + ApiModule, + HttpModule + ], + providers: [] +}) +export class AppModule {} +``` + +``` +// configuring providers +import { ApiModule, Configuration, ConfigurationParameters } from ''; + +export function apiConfigFactory (): Configuration => { + const params: ConfigurationParameters = { + // set configuration parameters here. + } + return new Configuration(params); +} + +@Module({ + imports: [ ApiModule.forRoot(apiConfigFactory) ], + declarations: [ AppComponent ], + providers: [], + bootstrap: [ AppComponent ] +}) +export class AppModule {} +``` + +``` +import { DefaultApi } from ''; + +export class AppComponent { + constructor(private apiGateway: DefaultApi) { } +} +``` + +Note: The ApiModule a dynamic module and instantiated once app wide. +This is to ensure that all services are treated as singletons. + +#### Using multiple swagger files / APIs / ApiModules +In order to use multiple `ApiModules` generated from different swagger files, +you can create an alias name when importing the modules +in order to avoid naming conflicts: +``` +import { ApiModule } from 'my-api-path'; +import { ApiModule as OtherApiModule } from 'my-other-api-path'; +import { HttpModule } from '@nestjs/axios'; + +@Module({ + imports: [ + ApiModule, + OtherApiModule, + HttpModule + ] +}) +export class AppModule { + +} +``` + + +### Set service base path +If different than the generated base path, during app bootstrap, you can provide the base path to your service. + +``` +import { BASE_PATH } from ''; + +bootstrap(AppComponent, [ + { provide: BASE_PATH, useValue: 'https://your-web-service.com' }, +]); +``` +or + +``` +import { BASE_PATH } from ''; + +@Module({ + imports: [], + declarations: [ AppComponent ], + providers: [ provide: BASE_PATH, useValue: 'https://your-web-service.com' ], + bootstrap: [ AppComponent ] +}) +export class AppModule {} +``` + +### Configuring the module with `forRootAsync` + +You can also use the Nestjs Config Module/Service to configure your app with `forRootAsync`. + +``` +@Module({ + imports: [ + ApiModule.forRootAsync({ + imports: [ConfigModule], + inject: [ConfigService], + useFactory: (config: ConfigService): Configuration => { + const params: ConfigurationParameters = { + // set configuration parameters here. + basePath: config.get('API_URL'), + }; + return new Configuration(params); + }, + }) + ], + declarations: [ AppComponent ], + providers: [], + bootstrap: [ AppComponent ] +}) +export class AppModule {} +``` + +#### Using @nestjs/cli +First extend your `src/environments/*.ts` files by adding the corresponding base path: + +``` +export const environment = { + production: false, + API_BASE_PATH: 'http://127.0.0.1:8080' +}; +``` + +In the src/app/app.module.ts: +``` +import { BASE_PATH } from ''; +import { environment } from '../environments/environment'; + +@Module({ + declarations: [ + AppComponent + ], + imports: [ ], + providers: [ + { + provide: 'BASE_PATH', + useValue: environment.API_BASE_PATH + } + ] +}) +export class AppModule { } +``` diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api.module.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api.module.ts new file mode 100644 index 000000000000..5743870b91c1 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api.module.ts @@ -0,0 +1,70 @@ +import { DynamicModule, Module, Global, Provider } from '@nestjs/common'; +import { HttpModule, HttpService } from '@nestjs/axios'; +import { AsyncConfiguration, Configuration, ConfigurationFactory } from './configuration'; + +import { DefaultService } from './api/default.service'; + +@Global() +@Module({ + imports: [ HttpModule ], + exports: [ + DefaultService + ], + providers: [ + DefaultService + ] +}) +export class ApiModule { + public static forRoot(configurationFactory: () => Configuration): DynamicModule { + return { + module: ApiModule, + providers: [ { provide: Configuration, useFactory: configurationFactory } ] + }; + } + + /** + * Register the module asynchronously. + */ + static forRootAsync(options: AsyncConfiguration): DynamicModule { + const providers = [...this.createAsyncProviders(options)]; + return { + module: ApiModule, + imports: options.imports || [], + providers, + exports: providers, + }; + } + + private static createAsyncProviders(options: AsyncConfiguration): Provider[] { + if (options.useClass) { + return [ + this.createAsyncConfigurationProvider(options), + { + provide: options.useClass, + useClass: options.useClass, + }, + ]; + } + return [this.createAsyncConfigurationProvider(options)]; + } + + private static createAsyncConfigurationProvider( + options: AsyncConfiguration, + ): Provider { + if (options.useFactory) { + return { + provide: Configuration, + useFactory: options.useFactory, + inject: options.inject || [], + }; + } + return { + provide: Configuration, + useFactory: async (optionsFactory: ConfigurationFactory) => + await optionsFactory.createConfiguration(), + inject: (options.useExisting && [options.useExisting]) || (options.useClass && [options.useClass]) || [], + }; + } + + constructor( httpService: HttpService) { } +} diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/api.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/api.ts new file mode 100644 index 000000000000..8e76619647f4 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/api.ts @@ -0,0 +1,3 @@ +export * from './default.service'; +import { DefaultService } from './default.service'; +export const APIS = [DefaultService]; diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts new file mode 100644 index 000000000000..e914dfe4e580 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts @@ -0,0 +1,127 @@ +/** + * Reserved param names + * Test reserved param names + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +/* tslint:disable:no-unused-variable member-ordering */ + +import { Injectable, Optional } from '@nestjs/common'; +import { HttpService } from '@nestjs/axios'; +import { AxiosResponse } from 'axios'; +import { Observable, from, of, switchMap } from 'rxjs'; +import { Configuration } from '../configuration'; +import { COLLECTION_FORMATS } from '../variables'; + +/** + * Request parameters for testReservedParamNames operation in DefaultService. + * @export + * @interface DefaultServiceTestReservedParamNamesRequest + */ +export interface DefaultServiceTestReservedParamNamesRequest { + /** + * Might conflict with rxjs import + * @type {string} + * @memberof DefaultServiceTestReservedParamNames + */ + readonly from: string + + /** + * Might conflict with headers const + * @type {string} + * @memberof DefaultServiceTestReservedParamNames + */ + readonly headers: string +} + + +@Injectable() +export class DefaultService { + + protected basePath = 'http://localhost'; + public defaultHeaders: Record = {}; + public configuration = new Configuration(); + protected httpClient: HttpService; + + constructor(httpClient: HttpService, @Optional() configuration: Configuration) { + this.configuration = configuration || this.configuration; + this.basePath = configuration?.basePath || this.basePath; + this.httpClient = configuration?.httpClient || httpClient; + } + + /** + * @param consumes string[] mime-types + * @return true: consumes contains 'multipart/form-data', false: otherwise + */ + private canConsumeForm(consumes: string[]): boolean { + const form = 'multipart/form-data'; + return consumes.includes(form); + } + + /** + * Test reserved param names + * + * @param {DefaultServiceTestReservedParamNamesRequest} requestParameters Request parameters. + */ + public testReservedParamNames(requestParameters: DefaultServiceTestReservedParamNamesRequest, ): Observable>; + public testReservedParamNames(requestParameters: DefaultServiceTestReservedParamNamesRequest, ): Observable { + if (requestParameters['from'] === null || requestParameters['from'] === undefined) { + throw new Error('Required parameter from was null or undefined when calling testReservedParamNames.'); + } + + if (requestParameters['headers'] === null || requestParameters['headers'] === undefined) { + throw new Error('Required parameter headers was null or undefined when calling testReservedParamNames.'); + } + + let queryParameters = new URLSearchParams(); + if (requestParameters['from'] !== undefined && requestParameters['from'] !== null) { + queryParameters.append('from', requestParameters['from']); + } + + let headers = {...this.defaultHeaders}; + if (requestParameters['headers'] !== undefined && requestParameters['headers'] !== null) { + headers['headers'] = String(requestParameters['headers']); + } + + let accessTokenObservable: Observable = of(null); + + // authentication (bearerAuth) required + if (typeof this.configuration.accessToken === 'function') { + accessTokenObservable = from(Promise.resolve(this.configuration.accessToken())); + } else if (this.configuration.accessToken) { + accessTokenObservable = from(Promise.resolve(this.configuration.accessToken)); + } + // to determine the Accept header + let httpHeaderAccepts: string[] = [ + ]; + const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts); + if (httpHeaderAcceptSelected != undefined) { + headers['Accept'] = httpHeaderAcceptSelected; + } + + // to determine the Content-Type header + const consumes: string[] = [ + ]; + return accessTokenObservable.pipe( + switchMap((accessToken) => { + if (accessToken) { + headers['Authorization'] = `Bearer ${accessToken}`; + } + + return this.httpClient.post(`${this.basePath}/test`, + null, + { + params: queryParameters, + withCredentials: this.configuration.withCredentials, + headers: headers + } + ); + }) + ); + } +} diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/configuration.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/configuration.ts new file mode 100644 index 000000000000..5db77aed7255 --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/configuration.ts @@ -0,0 +1,109 @@ +import type { HttpService } from '@nestjs/axios'; +import { ModuleMetadata, Type } from '@nestjs/common/interfaces'; + +export interface ConfigurationParameters { + apiKeys?: {[ key: string ]: string}; + username?: string; + password?: string; + accessToken?: string | Promise | (() => string | Promise); + basePath?: string; + withCredentials?: boolean; + httpClient?: HttpService; +} + +export class Configuration { + apiKeys?: {[ key: string ]: string}; + username?: string; + password?: string; + accessToken?: string | Promise | (() => string | Promise); + basePath?: string; + withCredentials?: boolean; + httpClient?: HttpService; + + constructor(configurationParameters: ConfigurationParameters = {}) { + this.apiKeys = configurationParameters.apiKeys; + this.username = configurationParameters.username; + this.password = configurationParameters.password; + this.accessToken = configurationParameters.accessToken; + this.basePath = configurationParameters.basePath; + this.withCredentials = configurationParameters.withCredentials; + this.httpClient = configurationParameters.httpClient; + } + + /** + * Select the correct content-type to use for a request. + * Uses {@link Configuration#isJsonMime} to determine the correct content-type. + * If no content type is found return the first found type if the contentTypes is not empty + * @param contentTypes - the array of content types that are available for selection + * @returns the selected content-type or undefined if no selection could be made. + */ + public selectHeaderContentType (contentTypes: string[]): string | undefined { + if (contentTypes.length == 0) { + return undefined; + } + + let type = contentTypes.find(x => this.isJsonMime(x)); + if (type === undefined) { + return contentTypes[0]; + } + return type; + } + + /** + * Select the correct accept content-type to use for a request. + * Uses {@link Configuration#isJsonMime} to determine the correct accept content-type. + * If no content type is found return the first found type if the contentTypes is not empty + * @param accepts - the array of content types that are available for selection. + * @returns the selected content-type or undefined if no selection could be made. + */ + public selectHeaderAccept(accepts: string[]): string | undefined { + if (accepts.length == 0) { + return undefined; + } + + let type = accepts.find(x => this.isJsonMime(x)); + if (type === undefined) { + return accepts[0]; + } + return type; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime != null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} + +export interface ConfigurationFactory { + createConfiguration(): Promise | Configuration; +} + +export interface AsyncConfiguration extends Pick { + /** + * The `useExisting` syntax allows you to create aliases for existing providers. + */ + useExisting?: Type; + /** + * The `useClass` syntax allows you to dynamically determine a class + * that a token should resolve to. + */ + useClass?: Type; + /** + * The `useFactory` syntax allows for creating providers dynamically. + */ + useFactory?: (...args: any[]) => Promise | Configuration; + /** + * Optional list of providers to be injected into the context of the Factory function. + */ + inject?: any[]; +} diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/git_push.sh b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/git_push.sh new file mode 100644 index 000000000000..f53a75d4fabe --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/git_push.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/index.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/index.ts new file mode 100644 index 000000000000..d20921b6d5de --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/index.ts @@ -0,0 +1,4 @@ +export * from './api/api'; +export * from './variables'; +export * from './configuration'; +export * from './api.module'; \ No newline at end of file diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/model/models.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/model/models.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/variables.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/variables.ts new file mode 100644 index 000000000000..d52a33f70e5b --- /dev/null +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/variables.ts @@ -0,0 +1,7 @@ + +export const COLLECTION_FORMATS = { + 'csv': ',', + 'tsv': ' ', + 'ssv': ' ', + 'pipes': '|' +} From eabc989dc7b5d9ef83352c08e61e85e7c841f262 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Mon, 25 Nov 2024 17:31:01 +0100 Subject: [PATCH 3/5] feat: quote params --- .../typescript-nestjs/api.service.mustache | 2 +- .../typescript-nestjs/modelGeneric.mustache | 2 +- .../typescript-nestjs/modelTaggedUnion.mustache | 4 ++-- .../builds/default/model/apiResponse.ts | 6 +++--- .../builds/default/model/category.ts | 4 ++-- .../builds/default/model/order.ts | 12 ++++++------ .../builds/default/model/pet.ts | 12 ++++++------ .../builds/default/model/tag.ts | 4 ++-- .../builds/default/model/user.ts | 16 ++++++++-------- .../builds/default/model/apiResponse.ts | 6 +++--- .../builds/default/model/category.ts | 4 ++-- .../builds/default/model/order.ts | 12 ++++++------ .../builds/default/model/pet.ts | 12 ++++++------ .../builds/default/model/tag.ts | 4 ++-- .../builds/default/model/user.ts | 16 ++++++++-------- .../reservedParamNames/api/default.service.ts | 4 ++-- 16 files changed, 60 insertions(+), 60 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache index 9fd95ba87f3f..9a74aa8db88b 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache @@ -35,7 +35,7 @@ export interface {{classname}}{{operationIdCamelCase}}Request { * @type {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> * @memberof {{classname}}{{operationIdCamelCase}} */ - readonly {{paramName}}{{^required}}?{{/required}}: {{{dataType}}} + readonly '{{paramName}}'{{^required}}?{{/required}}: {{{dataType}}} {{^-last}} {{/-last}} diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache index 43207b65e305..306a4e5982f2 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache @@ -5,6 +5,6 @@ export interface {{classname}}{{#allParents}}{{#-first}} extends {{/-first}}{{{. * {{{.}}} */ {{/description}} - {{#isReadOnly}}readonly {{/isReadOnly}}{{{name}}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}}; + {{#isReadOnly}}readonly {{/isReadOnly}}'{{{name}}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}}; {{/vars}} }{{>modelGenericEnums}} diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache index 24a9c0f0b60f..78394ca83846 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache @@ -10,7 +10,7 @@ export interface {{classname}} { {{>modelGenericAdditionalProperties}} * {{{.}}} */ {{/description}} - {{name}}{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}}; + '{{name}}'{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}}; {{/allVars}} } {{>modelGenericEnums}} @@ -18,4 +18,4 @@ export interface {{classname}} { {{>modelGenericAdditionalProperties}} {{^parent}} {{>modelGeneric}} {{/parent}} -{{/discriminator}} \ No newline at end of file +{{/discriminator}} diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts index 682ba478921e..98a604e8c9b5 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts @@ -15,8 +15,8 @@ * Describes the result of uploading an image resource */ export interface ApiResponse { - code?: number; - type?: string; - message?: string; + 'code'?: number; + 'type'?: string; + 'message'?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts index b988b6827a05..53cd597f732c 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts @@ -15,7 +15,7 @@ * A category for a pet */ export interface Category { - id?: number; - name?: string; + 'id'?: number; + 'name'?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts index a29bebe49065..6fe5ff4b6c37 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts @@ -15,15 +15,15 @@ * An order for a pets from the pet store */ export interface Order { - id?: number; - petId?: number; - quantity?: number; - shipDate?: string; + 'id'?: number; + 'petId'?: number; + 'quantity'?: number; + 'shipDate'?: string; /** * Order Status */ - status?: Order.StatusEnum; - complete?: boolean; + 'status'?: Order.StatusEnum; + 'complete'?: boolean; } export namespace Order { export type StatusEnum = 'placed' | 'approved' | 'delivered'; diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts index e0404395f91c..84986996e282 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts @@ -17,15 +17,15 @@ import { Tag } from './tag'; * A pet for sale in the pet store */ export interface Pet { - id?: number; - category?: Category; - name: string; - photoUrls: Array; - tags?: Array; + 'id'?: number; + 'category'?: Category; + 'name': string; + 'photoUrls': Array; + 'tags'?: Array; /** * pet status in the store */ - status?: Pet.StatusEnum; + 'status'?: Pet.StatusEnum; } export namespace Pet { export type StatusEnum = 'available' | 'pending' | 'sold'; diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts index b6ff210e8df4..9fd8a41f47ec 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts @@ -15,7 +15,7 @@ * A tag for a pet */ export interface Tag { - id?: number; - name?: string; + 'id'?: number; + 'name'?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts index fce51005300c..db12e3c1ca24 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts @@ -15,16 +15,16 @@ * A User who is purchasing from the pet store */ export interface User { - id?: number; - username?: string; - firstName?: string; - lastName?: string; - email?: string; - password?: string; - phone?: string; + 'id'?: number; + 'username'?: string; + 'firstName'?: string; + 'lastName'?: string; + 'email'?: string; + 'password'?: string; + 'phone'?: string; /** * User Status */ - userStatus?: number; + 'userStatus'?: number; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts index 682ba478921e..98a604e8c9b5 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts @@ -15,8 +15,8 @@ * Describes the result of uploading an image resource */ export interface ApiResponse { - code?: number; - type?: string; - message?: string; + 'code'?: number; + 'type'?: string; + 'message'?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts index b988b6827a05..53cd597f732c 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts @@ -15,7 +15,7 @@ * A category for a pet */ export interface Category { - id?: number; - name?: string; + 'id'?: number; + 'name'?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts index a29bebe49065..6fe5ff4b6c37 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts @@ -15,15 +15,15 @@ * An order for a pets from the pet store */ export interface Order { - id?: number; - petId?: number; - quantity?: number; - shipDate?: string; + 'id'?: number; + 'petId'?: number; + 'quantity'?: number; + 'shipDate'?: string; /** * Order Status */ - status?: Order.StatusEnum; - complete?: boolean; + 'status'?: Order.StatusEnum; + 'complete'?: boolean; } export namespace Order { export type StatusEnum = 'placed' | 'approved' | 'delivered'; diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts index e0404395f91c..84986996e282 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts @@ -17,15 +17,15 @@ import { Tag } from './tag'; * A pet for sale in the pet store */ export interface Pet { - id?: number; - category?: Category; - name: string; - photoUrls: Array; - tags?: Array; + 'id'?: number; + 'category'?: Category; + 'name': string; + 'photoUrls': Array; + 'tags'?: Array; /** * pet status in the store */ - status?: Pet.StatusEnum; + 'status'?: Pet.StatusEnum; } export namespace Pet { export type StatusEnum = 'available' | 'pending' | 'sold'; diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts index b6ff210e8df4..9fd8a41f47ec 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts @@ -15,7 +15,7 @@ * A tag for a pet */ export interface Tag { - id?: number; - name?: string; + 'id'?: number; + 'name'?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts index fce51005300c..db12e3c1ca24 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts @@ -15,16 +15,16 @@ * A User who is purchasing from the pet store */ export interface User { - id?: number; - username?: string; - firstName?: string; - lastName?: string; - email?: string; - password?: string; - phone?: string; + 'id'?: number; + 'username'?: string; + 'firstName'?: string; + 'lastName'?: string; + 'email'?: string; + 'password'?: string; + 'phone'?: string; /** * User Status */ - userStatus?: number; + 'userStatus'?: number; } diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts index e914dfe4e580..afd6e3552e93 100644 --- a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts @@ -29,14 +29,14 @@ export interface DefaultServiceTestReservedParamNamesRequest { * @type {string} * @memberof DefaultServiceTestReservedParamNames */ - readonly from: string + readonly 'from': string /** * Might conflict with headers const * @type {string} * @memberof DefaultServiceTestReservedParamNames */ - readonly headers: string + readonly 'headers': string } From 9c7fcfa5e9685d09172e7fa03349d8653d0ad0c2 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Wed, 27 Nov 2024 17:28:26 +0100 Subject: [PATCH 4/5] feat: improve with reservedWords --- docs/generators/typescript-nestjs.md | 2 + .../TypeScriptNestjsClientCodegen.java | 158 ++++++++++++++++++ .../typescript-nestjs/api.service.mustache | 46 +++-- .../typescript-nestjs/modelGeneric.mustache | 2 +- .../modelTaggedUnion.mustache | 2 +- .../reserved-param-names.yaml | 6 + .../builds/default/model/apiResponse.ts | 6 +- .../builds/default/model/category.ts | 4 +- .../builds/default/model/order.ts | 12 +- .../builds/default/model/pet.ts | 12 +- .../builds/default/model/tag.ts | 4 +- .../builds/default/model/user.ts | 16 +- .../builds/default/model/apiResponse.ts | 6 +- .../builds/default/model/category.ts | 4 +- .../builds/default/model/order.ts | 12 +- .../builds/default/model/pet.ts | 12 +- .../builds/default/model/tag.ts | 4 +- .../builds/default/model/user.ts | 16 +- .../reservedParamNames/api/default.service.ts | 36 +++- 19 files changed, 278 insertions(+), 82 deletions(-) diff --git a/docs/generators/typescript-nestjs.md b/docs/generators/typescript-nestjs.md index 2055133b6b89..47037f98f6b0 100644 --- a/docs/generators/typescript-nestjs.md +++ b/docs/generators/typescript-nestjs.md @@ -116,9 +116,11 @@ These options may be applied as additional-properties (cli) or configOptions (pl
  • float
  • for
  • formParams
  • +
  • from
  • function
  • goto
  • headerParams
  • +
  • headers
  • if
  • implements
  • import
  • diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java index 520d69e2d62d..770167b0e765 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java @@ -17,6 +17,8 @@ package org.openapitools.codegen.languages; import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.RequestBody; import lombok.Getter; import lombok.Setter; import org.openapitools.codegen.*; @@ -88,6 +90,8 @@ public TypeScriptNestjsClientCodegen() { apiPackage = "api"; modelPackage = "model"; + reservedWords.addAll(Arrays.asList("from", "headers")); + this.cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json")); this.cliOptions.add(CliOption.newBoolean(WITH_INTERFACES, @@ -265,6 +269,34 @@ private boolean isLanguageGenericType(String type) { return false; } + @Override + public List fromRequestBodyToFormParameters(RequestBody body, Set imports) { + List superParams = super.fromRequestBodyToFormParameters(body, imports); + List extendedParams = new ArrayList(); + for (CodegenParameter cp : superParams) { + extendedParams.add(new ExtendedCodegenParameter(cp)); + } + return extendedParams; + } + + @Override + public ExtendedCodegenParameter fromParameter(Parameter parameter, Set imports) { + CodegenParameter cp = super.fromParameter(parameter, imports); + return new ExtendedCodegenParameter(cp); + } + + @Override + public CodegenParameter fromFormProperty(String name, Schema propertySchema, Set imports) { + CodegenParameter cp = super.fromFormProperty(name, propertySchema, imports); + return new ExtendedCodegenParameter(cp); + } + + @Override + public CodegenParameter fromRequestBody(RequestBody body, Set imports, String bodyParameterName) { + CodegenParameter cp = super.fromRequestBody(body, imports, bodyParameterName); + return new ExtendedCodegenParameter(cp); + } + @Override public void postProcessParameter(CodegenParameter parameter) { super.postProcessParameter(parameter); @@ -327,6 +359,12 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap operations, L // Overwrite path to TypeScript template string, after applying everything we just did. op.path = pathBuffer.toString(); + + for (CodegenParameter cpParam : op.allParams) { + ExtendedCodegenParameter param = (ExtendedCodegenParameter) cpParam; + + param.hasSanitizedName = !param.baseName.equals(param.paramName); + } } operations.put("hasSomeFormParams", hasSomeFormParams); @@ -482,6 +520,126 @@ public String removeModelPrefixSuffix(String name) { return result; } + public class ExtendedCodegenParameter extends CodegenParameter { + public boolean hasSanitizedName = false; + + public ExtendedCodegenParameter(CodegenParameter cp) { + super(); + + this.isFormParam = cp.isFormParam; + this.isQueryParam = cp.isQueryParam; + this.isPathParam = cp.isPathParam; + this.isHeaderParam = cp.isHeaderParam; + this.isCookieParam = cp.isCookieParam; + this.isBodyParam = cp.isBodyParam; + this.isContainer = cp.isContainer; + this.isCollectionFormatMulti = cp.isCollectionFormatMulti; + this.isPrimitiveType = cp.isPrimitiveType; + this.isModel = cp.isModel; + this.isExplode = cp.isExplode; + this.baseName = cp.baseName; + this.paramName = cp.paramName; + this.dataType = cp.dataType; + this.datatypeWithEnum = cp.datatypeWithEnum; + this.dataFormat = cp.dataFormat; + this.contentType = cp.contentType; + this.collectionFormat = cp.collectionFormat; + this.description = cp.description; + this.unescapedDescription = cp.unescapedDescription; + this.baseType = cp.baseType; + this.defaultValue = cp.defaultValue; + this.enumName = cp.enumName; + this.style = cp.style; + this.nameInLowerCase = cp.nameInLowerCase; + this.example = cp.example; + this.jsonSchema = cp.jsonSchema; + this.isString = cp.isString; + this.isNumeric = cp.isNumeric; + this.isInteger = cp.isInteger; + this.isLong = cp.isLong; + this.isNumber = cp.isNumber; + this.isFloat = cp.isFloat; + this.isDouble = cp.isDouble; + this.isDecimal = cp.isDecimal; + this.isByteArray = cp.isByteArray; + this.isBinary = cp.isBinary; + this.isBoolean = cp.isBoolean; + this.isDate = cp.isDate; + this.isDateTime = cp.isDateTime; + this.isUuid = cp.isUuid; + this.isUri = cp.isUri; + this.isEmail = cp.isEmail; + this.isFreeFormObject = cp.isFreeFormObject; + this.isAnyType = cp.isAnyType; + this.isArray = cp.isArray; + this.isMap = cp.isMap; + this.isFile = cp.isFile; + this.isEnum = cp.isEnum; + this.isEnumRef = cp.isEnumRef; + this._enum = cp._enum; + this.allowableValues = cp.allowableValues; + this.items = cp.items; + this.additionalProperties = cp.additionalProperties; + this.vars = cp.vars; + this.requiredVars = cp.requiredVars; + this.mostInnerItems = cp.mostInnerItems; + this.vendorExtensions = cp.vendorExtensions; + this.hasValidation = cp.hasValidation; + this.isNullable = cp.isNullable; + this.required = cp.required; + this.maximum = cp.maximum; + this.exclusiveMaximum = cp.exclusiveMaximum; + this.minimum = cp.minimum; + this.exclusiveMinimum = cp.exclusiveMinimum; + this.maxLength = cp.maxLength; + this.minLength = cp.minLength; + this.pattern = cp.pattern; + this.maxItems = cp.maxItems; + this.minItems = cp.minItems; + this.uniqueItems = cp.uniqueItems; + this.multipleOf = cp.multipleOf; + this.setHasVars(cp.getHasVars()); + this.setHasRequired(cp.getHasRequired()); + this.setMaxProperties(cp.getMaxProperties()); + this.setMinProperties(cp.getMinProperties()); + } + + @Override + public ExtendedCodegenParameter copy() { + CodegenParameter superCopy = super.copy(); + ExtendedCodegenParameter output = new ExtendedCodegenParameter(superCopy); + output.hasSanitizedName = this.hasSanitizedName; + return output; + } + + @Override + public boolean equals(Object o) { + if (o == null) + return false; + + if (this.getClass() != o.getClass()) + return false; + + boolean result = super.equals(o); + ExtendedCodegenParameter that = (ExtendedCodegenParameter) o; + return result && hasSanitizedName == that.hasSanitizedName; + } + + @Override + public int hashCode() { + int superHash = super.hashCode(); + return Objects.hash(superHash, hasSanitizedName); + } + + @Override + public String toString() { + String superString = super.toString(); + final StringBuilder sb = new StringBuilder(superString); + sb.append(", hasSanitizedName=").append(hasSanitizedName); + return sb.toString(); + } + } + /** * Validates that the given string value only contains '-', '.' and alpha numeric characters. * Throws an IllegalArgumentException, if the string contains any other characters. diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache index 9a74aa8db88b..dc67f59d27fe 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache @@ -35,7 +35,7 @@ export interface {{classname}}{{operationIdCamelCase}}Request { * @type {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> * @memberof {{classname}}{{operationIdCamelCase}} */ - readonly '{{paramName}}'{{^required}}?{{/required}}: {{{dataType}}} + readonly {{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{paramName}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{{dataType}}} {{^-last}} {{/-last}} @@ -102,13 +102,23 @@ export class {{classname}} { public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable>; public {{nickname}}({{#allParams}}{{^isConstEnumParam}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/isConstEnumParam}}{{/allParams}}): Observable { {{/useSingleRequestParameter}} +{{#allParams.0}} +{{#useSingleRequestParameter}} + const { + {{#allParams}} + {{#hasSanitizedName}}'{{{baseName}}}': {{/hasSanitizedName}}{{paramName}}, + {{/allParams}} + } = requestParameters; + +{{/useSingleRequestParameter}} +{{/allParams.0}} {{#allParams}} {{#required}} {{#isConstEnumParam}} let {{paramName}} = {{{dataType}}}; {{/isConstEnumParam}} {{^isConstEnumParam}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} === null || {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} === undefined) { + if ({{paramName}} === null || {{paramName}} === undefined) { throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.'); } @@ -119,24 +129,24 @@ export class {{classname}} { let queryParameters = new URLSearchParams(); {{#queryParams}} {{#isArray}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) { + if ({{paramName}}) { {{#isCollectionFormatMulti}} - {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.forEach((element) => { + {{paramName}}.forEach((element) => { queryParameters.append('{{baseName}}', element); }) {{/isCollectionFormatMulti}} {{^isCollectionFormatMulti}} - queryParameters['{{baseName}}'] = {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); + queryParameters['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); {{/isCollectionFormatMulti}} } {{/isArray}} {{^isArray}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined && {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== null) { + if ({{paramName}} !== undefined && {{paramName}} !== null) { {{#isDateTime}} - queryParameters.append('{{baseName}}', ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}).toISOString()); + queryParameters.append('{{baseName}}', ({{paramName}}).toISOString()); {{/isDateTime}} {{^isDateTime}} - queryParameters.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}); + queryParameters.append('{{baseName}}', {{paramName}}); {{/isDateTime}} } {{/isArray}} @@ -146,13 +156,13 @@ export class {{classname}} { let headers = {...this.defaultHeaders}; {{#headerParams}} {{#isArray}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) { - headers['{{baseName}}'] = {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); + if ({{paramName}}) { + headers['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']); } {{/isArray}} {{^isArray}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined && {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== null) { - headers['{{baseName}}'] = String({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}); + if ({{paramName}} !== undefined && {{paramName}} !== null) { + headers['{{baseName}}'] = String({{paramName}}); } {{/isArray}} {{/headerParams}} @@ -246,20 +256,20 @@ export class {{classname}} { {{#formParams}} {{#isArray}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}) { + if ({{paramName}}) { {{#isCollectionFormatMulti}} - {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.forEach((element) => { + {{paramName}}.forEach((element) => { formParams!.append('{{baseName}}', element); }) {{/isCollectionFormatMulti}} {{^isCollectionFormatMulti}} - formParams!.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])); + formParams!.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])); {{/isCollectionFormatMulti}} } {{/isArray}} {{^isArray}} - if ({{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}} !== undefined) { - formParams!.append('{{baseName}}', {{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}); + if ({{paramName}} !== undefined) { + formParams!.append('{{baseName}}', {{paramName}}); } {{/isArray}} {{/formParams}} @@ -272,7 +282,7 @@ export class {{classname}} { } return this.httpClient.{{httpMethod}}{{^isResponseFile}}<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>{{/isResponseFile}}(`${this.basePath}{{{path}}}`,{{#isBodyAllowed}} - {{#bodyParam}}{{#useSingleRequestParameter}}requestParameters['{{/useSingleRequestParameter}}{{paramName}}{{#useSingleRequestParameter}}']{{/useSingleRequestParameter}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}} + {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams!.toString() : formParams!{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}} { {{#hasQueryParams}} params: queryParameters, diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache index 306a4e5982f2..720aac912881 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelGeneric.mustache @@ -5,6 +5,6 @@ export interface {{classname}}{{#allParents}}{{#-first}} extends {{/-first}}{{{. * {{{.}}} */ {{/description}} - {{#isReadOnly}}readonly {{/isReadOnly}}'{{{name}}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}}; + {{#isReadOnly}}readonly {{/isReadOnly}}{{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{name}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}}; {{/vars}} }{{>modelGenericEnums}} diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache index 78394ca83846..754c1db278ba 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/modelTaggedUnion.mustache @@ -10,7 +10,7 @@ export interface {{classname}} { {{>modelGenericAdditionalProperties}} * {{{.}}} */ {{/description}} - '{{name}}'{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}}; + {{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{name}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{#discriminatorValue}}'{{.}}'{{/discriminatorValue}}{{^discriminatorValue}}{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{/discriminatorValue}}{{#isNullable}} | null{{/isNullable}}; {{/allVars}} } {{>modelGenericEnums}} diff --git a/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml b/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml index 91f3b8588afc..ab02beffe8c6 100644 --- a/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/typescript-nestjs/reserved-param-names.yaml @@ -12,6 +12,12 @@ paths: description: '' operationId: testReservedParamNames parameters: + - name: notReserved + in: query + description: Should not be treated as a reserved param name + required: true + schema: + type: string - name: from in: query description: Might conflict with rxjs import diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts index 98a604e8c9b5..682ba478921e 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/apiResponse.ts @@ -15,8 +15,8 @@ * Describes the result of uploading an image resource */ export interface ApiResponse { - 'code'?: number; - 'type'?: string; - 'message'?: string; + code?: number; + type?: string; + message?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts index 53cd597f732c..b988b6827a05 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/category.ts @@ -15,7 +15,7 @@ * A category for a pet */ export interface Category { - 'id'?: number; - 'name'?: string; + id?: number; + name?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts index 6fe5ff4b6c37..a29bebe49065 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/order.ts @@ -15,15 +15,15 @@ * An order for a pets from the pet store */ export interface Order { - 'id'?: number; - 'petId'?: number; - 'quantity'?: number; - 'shipDate'?: string; + id?: number; + petId?: number; + quantity?: number; + shipDate?: string; /** * Order Status */ - 'status'?: Order.StatusEnum; - 'complete'?: boolean; + status?: Order.StatusEnum; + complete?: boolean; } export namespace Order { export type StatusEnum = 'placed' | 'approved' | 'delivered'; diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts index 84986996e282..e0404395f91c 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/pet.ts @@ -17,15 +17,15 @@ import { Tag } from './tag'; * A pet for sale in the pet store */ export interface Pet { - 'id'?: number; - 'category'?: Category; - 'name': string; - 'photoUrls': Array; - 'tags'?: Array; + id?: number; + category?: Category; + name: string; + photoUrls: Array; + tags?: Array; /** * pet status in the store */ - 'status'?: Pet.StatusEnum; + status?: Pet.StatusEnum; } export namespace Pet { export type StatusEnum = 'available' | 'pending' | 'sold'; diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts index 9fd8a41f47ec..b6ff210e8df4 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/tag.ts @@ -15,7 +15,7 @@ * A tag for a pet */ export interface Tag { - 'id'?: number; - 'name'?: string; + id?: number; + name?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts index db12e3c1ca24..fce51005300c 100644 --- a/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts +++ b/samples/client/petstore/typescript-nestjs-v6-provided-in-root/builds/default/model/user.ts @@ -15,16 +15,16 @@ * A User who is purchasing from the pet store */ export interface User { - 'id'?: number; - 'username'?: string; - 'firstName'?: string; - 'lastName'?: string; - 'email'?: string; - 'password'?: string; - 'phone'?: string; + id?: number; + username?: string; + firstName?: string; + lastName?: string; + email?: string; + password?: string; + phone?: string; /** * User Status */ - 'userStatus'?: number; + userStatus?: number; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts index 98a604e8c9b5..682ba478921e 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/apiResponse.ts @@ -15,8 +15,8 @@ * Describes the result of uploading an image resource */ export interface ApiResponse { - 'code'?: number; - 'type'?: string; - 'message'?: string; + code?: number; + type?: string; + message?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts index 53cd597f732c..b988b6827a05 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/category.ts @@ -15,7 +15,7 @@ * A category for a pet */ export interface Category { - 'id'?: number; - 'name'?: string; + id?: number; + name?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts index 6fe5ff4b6c37..a29bebe49065 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/order.ts @@ -15,15 +15,15 @@ * An order for a pets from the pet store */ export interface Order { - 'id'?: number; - 'petId'?: number; - 'quantity'?: number; - 'shipDate'?: string; + id?: number; + petId?: number; + quantity?: number; + shipDate?: string; /** * Order Status */ - 'status'?: Order.StatusEnum; - 'complete'?: boolean; + status?: Order.StatusEnum; + complete?: boolean; } export namespace Order { export type StatusEnum = 'placed' | 'approved' | 'delivered'; diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts index 84986996e282..e0404395f91c 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/pet.ts @@ -17,15 +17,15 @@ import { Tag } from './tag'; * A pet for sale in the pet store */ export interface Pet { - 'id'?: number; - 'category'?: Category; - 'name': string; - 'photoUrls': Array; - 'tags'?: Array; + id?: number; + category?: Category; + name: string; + photoUrls: Array; + tags?: Array; /** * pet status in the store */ - 'status'?: Pet.StatusEnum; + status?: Pet.StatusEnum; } export namespace Pet { export type StatusEnum = 'available' | 'pending' | 'sold'; diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts index 9fd8a41f47ec..b6ff210e8df4 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/tag.ts @@ -15,7 +15,7 @@ * A tag for a pet */ export interface Tag { - 'id'?: number; - 'name'?: string; + id?: number; + name?: string; } diff --git a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts index db12e3c1ca24..fce51005300c 100644 --- a/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts +++ b/samples/client/petstore/typescript-nestjs-v8-provided-in-root/builds/default/model/user.ts @@ -15,16 +15,16 @@ * A User who is purchasing from the pet store */ export interface User { - 'id'?: number; - 'username'?: string; - 'firstName'?: string; - 'lastName'?: string; - 'email'?: string; - 'password'?: string; - 'phone'?: string; + id?: number; + username?: string; + firstName?: string; + lastName?: string; + email?: string; + password?: string; + phone?: string; /** * User Status */ - 'userStatus'?: number; + userStatus?: number; } diff --git a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts index afd6e3552e93..c41aa37ec06b 100644 --- a/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts +++ b/samples/client/petstore/typescript-nestjs/builds/reservedParamNames/api/default.service.ts @@ -24,6 +24,13 @@ import { COLLECTION_FORMATS } from '../variables'; * @interface DefaultServiceTestReservedParamNamesRequest */ export interface DefaultServiceTestReservedParamNamesRequest { + /** + * Should not be treated as a reserved param name + * @type {string} + * @memberof DefaultServiceTestReservedParamNames + */ + readonly notReserved: string + /** * Might conflict with rxjs import * @type {string} @@ -70,22 +77,35 @@ export class DefaultService { */ public testReservedParamNames(requestParameters: DefaultServiceTestReservedParamNamesRequest, ): Observable>; public testReservedParamNames(requestParameters: DefaultServiceTestReservedParamNamesRequest, ): Observable { - if (requestParameters['from'] === null || requestParameters['from'] === undefined) { - throw new Error('Required parameter from was null or undefined when calling testReservedParamNames.'); + const { + notReserved, + 'from': _from, + 'headers': _headers, + } = requestParameters; + + if (notReserved === null || notReserved === undefined) { + throw new Error('Required parameter notReserved was null or undefined when calling testReservedParamNames.'); + } + + if (_from === null || _from === undefined) { + throw new Error('Required parameter _from was null or undefined when calling testReservedParamNames.'); } - if (requestParameters['headers'] === null || requestParameters['headers'] === undefined) { - throw new Error('Required parameter headers was null or undefined when calling testReservedParamNames.'); + if (_headers === null || _headers === undefined) { + throw new Error('Required parameter _headers was null or undefined when calling testReservedParamNames.'); } let queryParameters = new URLSearchParams(); - if (requestParameters['from'] !== undefined && requestParameters['from'] !== null) { - queryParameters.append('from', requestParameters['from']); + if (notReserved !== undefined && notReserved !== null) { + queryParameters.append('notReserved', notReserved); + } + if (_from !== undefined && _from !== null) { + queryParameters.append('from', _from); } let headers = {...this.defaultHeaders}; - if (requestParameters['headers'] !== undefined && requestParameters['headers'] !== null) { - headers['headers'] = String(requestParameters['headers']); + if (_headers !== undefined && _headers !== null) { + headers['headers'] = String(_headers); } let accessTokenObservable: Observable = of(null); From d87f086ed0b3be5bf965043c80bc27077a8a3dc0 Mon Sep 17 00:00:00 2001 From: Gregory Merlet Date: Fri, 29 Nov 2024 16:31:12 +0100 Subject: [PATCH 5/5] feat: use vendorExtensions instead of extending CodegenParameter --- .../TypeScriptNestjsClientCodegen.java | 156 +----------------- .../typescript-nestjs/api.service.mustache | 4 +- 2 files changed, 4 insertions(+), 156 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java index 770167b0e765..e12e8b2f030f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNestjsClientCodegen.java @@ -17,8 +17,6 @@ package org.openapitools.codegen.languages; import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.parameters.Parameter; -import io.swagger.v3.oas.models.parameters.RequestBody; import lombok.Getter; import lombok.Setter; import org.openapitools.codegen.*; @@ -269,34 +267,6 @@ private boolean isLanguageGenericType(String type) { return false; } - @Override - public List fromRequestBodyToFormParameters(RequestBody body, Set imports) { - List superParams = super.fromRequestBodyToFormParameters(body, imports); - List extendedParams = new ArrayList(); - for (CodegenParameter cp : superParams) { - extendedParams.add(new ExtendedCodegenParameter(cp)); - } - return extendedParams; - } - - @Override - public ExtendedCodegenParameter fromParameter(Parameter parameter, Set imports) { - CodegenParameter cp = super.fromParameter(parameter, imports); - return new ExtendedCodegenParameter(cp); - } - - @Override - public CodegenParameter fromFormProperty(String name, Schema propertySchema, Set imports) { - CodegenParameter cp = super.fromFormProperty(name, propertySchema, imports); - return new ExtendedCodegenParameter(cp); - } - - @Override - public CodegenParameter fromRequestBody(RequestBody body, Set imports, String bodyParameterName) { - CodegenParameter cp = super.fromRequestBody(body, imports, bodyParameterName); - return new ExtendedCodegenParameter(cp); - } - @Override public void postProcessParameter(CodegenParameter parameter) { super.postProcessParameter(parameter); @@ -360,10 +330,8 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap operations, L // Overwrite path to TypeScript template string, after applying everything we just did. op.path = pathBuffer.toString(); - for (CodegenParameter cpParam : op.allParams) { - ExtendedCodegenParameter param = (ExtendedCodegenParameter) cpParam; - - param.hasSanitizedName = !param.baseName.equals(param.paramName); + for (CodegenParameter param : op.allParams) { + param.vendorExtensions.putIfAbsent("x-param-has-sanitized-name", !param.baseName.equals(param.paramName)); } } @@ -520,126 +488,6 @@ public String removeModelPrefixSuffix(String name) { return result; } - public class ExtendedCodegenParameter extends CodegenParameter { - public boolean hasSanitizedName = false; - - public ExtendedCodegenParameter(CodegenParameter cp) { - super(); - - this.isFormParam = cp.isFormParam; - this.isQueryParam = cp.isQueryParam; - this.isPathParam = cp.isPathParam; - this.isHeaderParam = cp.isHeaderParam; - this.isCookieParam = cp.isCookieParam; - this.isBodyParam = cp.isBodyParam; - this.isContainer = cp.isContainer; - this.isCollectionFormatMulti = cp.isCollectionFormatMulti; - this.isPrimitiveType = cp.isPrimitiveType; - this.isModel = cp.isModel; - this.isExplode = cp.isExplode; - this.baseName = cp.baseName; - this.paramName = cp.paramName; - this.dataType = cp.dataType; - this.datatypeWithEnum = cp.datatypeWithEnum; - this.dataFormat = cp.dataFormat; - this.contentType = cp.contentType; - this.collectionFormat = cp.collectionFormat; - this.description = cp.description; - this.unescapedDescription = cp.unescapedDescription; - this.baseType = cp.baseType; - this.defaultValue = cp.defaultValue; - this.enumName = cp.enumName; - this.style = cp.style; - this.nameInLowerCase = cp.nameInLowerCase; - this.example = cp.example; - this.jsonSchema = cp.jsonSchema; - this.isString = cp.isString; - this.isNumeric = cp.isNumeric; - this.isInteger = cp.isInteger; - this.isLong = cp.isLong; - this.isNumber = cp.isNumber; - this.isFloat = cp.isFloat; - this.isDouble = cp.isDouble; - this.isDecimal = cp.isDecimal; - this.isByteArray = cp.isByteArray; - this.isBinary = cp.isBinary; - this.isBoolean = cp.isBoolean; - this.isDate = cp.isDate; - this.isDateTime = cp.isDateTime; - this.isUuid = cp.isUuid; - this.isUri = cp.isUri; - this.isEmail = cp.isEmail; - this.isFreeFormObject = cp.isFreeFormObject; - this.isAnyType = cp.isAnyType; - this.isArray = cp.isArray; - this.isMap = cp.isMap; - this.isFile = cp.isFile; - this.isEnum = cp.isEnum; - this.isEnumRef = cp.isEnumRef; - this._enum = cp._enum; - this.allowableValues = cp.allowableValues; - this.items = cp.items; - this.additionalProperties = cp.additionalProperties; - this.vars = cp.vars; - this.requiredVars = cp.requiredVars; - this.mostInnerItems = cp.mostInnerItems; - this.vendorExtensions = cp.vendorExtensions; - this.hasValidation = cp.hasValidation; - this.isNullable = cp.isNullable; - this.required = cp.required; - this.maximum = cp.maximum; - this.exclusiveMaximum = cp.exclusiveMaximum; - this.minimum = cp.minimum; - this.exclusiveMinimum = cp.exclusiveMinimum; - this.maxLength = cp.maxLength; - this.minLength = cp.minLength; - this.pattern = cp.pattern; - this.maxItems = cp.maxItems; - this.minItems = cp.minItems; - this.uniqueItems = cp.uniqueItems; - this.multipleOf = cp.multipleOf; - this.setHasVars(cp.getHasVars()); - this.setHasRequired(cp.getHasRequired()); - this.setMaxProperties(cp.getMaxProperties()); - this.setMinProperties(cp.getMinProperties()); - } - - @Override - public ExtendedCodegenParameter copy() { - CodegenParameter superCopy = super.copy(); - ExtendedCodegenParameter output = new ExtendedCodegenParameter(superCopy); - output.hasSanitizedName = this.hasSanitizedName; - return output; - } - - @Override - public boolean equals(Object o) { - if (o == null) - return false; - - if (this.getClass() != o.getClass()) - return false; - - boolean result = super.equals(o); - ExtendedCodegenParameter that = (ExtendedCodegenParameter) o; - return result && hasSanitizedName == that.hasSanitizedName; - } - - @Override - public int hashCode() { - int superHash = super.hashCode(); - return Objects.hash(superHash, hasSanitizedName); - } - - @Override - public String toString() { - String superString = super.toString(); - final StringBuilder sb = new StringBuilder(superString); - sb.append(", hasSanitizedName=").append(hasSanitizedName); - return sb.toString(); - } - } - /** * Validates that the given string value only contains '-', '.' and alpha numeric characters. * Throws an IllegalArgumentException, if the string contains any other characters. diff --git a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache index dc67f59d27fe..12bf8d238860 100644 --- a/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-nestjs/api.service.mustache @@ -35,7 +35,7 @@ export interface {{classname}}{{operationIdCamelCase}}Request { * @type {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> * @memberof {{classname}}{{operationIdCamelCase}} */ - readonly {{#hasSanitizedName}}'{{{baseName}}}'{{/hasSanitizedName}}{{^hasSanitizedName}}{{{paramName}}}{{/hasSanitizedName}}{{^required}}?{{/required}}: {{{dataType}}} + readonly {{#vendorExtensions.x-param-has-sanitized-name}}'{{{baseName}}}'{{/vendorExtensions.x-param-has-sanitized-name}}{{^vendorExtensions.x-param-has-sanitized-name}}{{{paramName}}}{{/vendorExtensions.x-param-has-sanitized-name}}{{^required}}?{{/required}}: {{{dataType}}} {{^-last}} {{/-last}} @@ -106,7 +106,7 @@ export class {{classname}} { {{#useSingleRequestParameter}} const { {{#allParams}} - {{#hasSanitizedName}}'{{{baseName}}}': {{/hasSanitizedName}}{{paramName}}, + {{#vendorExtensions.x-param-has-sanitized-name}}'{{{baseName}}}': {{/vendorExtensions.x-param-has-sanitized-name}}{{paramName}}, {{/allParams}} } = requestParameters;