Skip to content

Commit b3f1196

Browse files
davidgamerodavid
andauthored
[typescript] add call-time middleware support (#20430)
* add call-time middleware * update dependencies to run on current tsc * exclude middleware from inversify * update samples * update service * space * inversify exclude * braces * import in objectparamapi * add integration test for middleware * switch to configuration options merge * enable options on non inversify builds * remove unused middlware export * remove merge strategy from inversify * gen samples * remove old middlware imports * tab to space * separate promise and observable options * gen samples * use allmiddleware var across inversify * generate encode samples again * add middleware call-order tests for default typescript build * type refactor * add semicolons, default replace, let to const --------- Co-authored-by: david <david@dmba.local>
1 parent 60bae73 commit b3f1196

File tree

127 files changed

+17929
-4694
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+17929
-4694
lines changed

modules/openapi-generator/src/main/resources/typescript/api/api.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export class {{classname}}RequestFactory extends BaseAPIRequestFactory {
183183
{{/authMethods}}
184184

185185
{{^useInversify}}
186-
const defaultAuth: SecurityAuthentication | undefined = _options?.authMethods?.default || this.configuration?.authMethods?.default
186+
const defaultAuth: SecurityAuthentication | undefined = _config?.authMethods?.default
187187
if (defaultAuth?.applySecurityAuthentication) {
188188
await defaultAuth?.applySecurityAuthentication(requestContext);
189189
}

modules/openapi-generator/src/main/resources/typescript/configuration.mustache

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,25 @@ import { JQueryHttpLibrary as DefaultHttpLibrary } from "./http/jquery";
1111
import { BaseServerConfiguration, server1 } from "./servers{{importFileExtension}}";
1212
import { configureAuthMethods, AuthMethods, AuthMethodsConfiguration } from "./auth/auth{{importFileExtension}}";
1313

14-
export interface Configuration {
15-
readonly baseServer: BaseServerConfiguration;
16-
readonly httpApi: HttpLibrary;
17-
readonly middleware: Middleware[];
18-
readonly authMethods: AuthMethods;
14+
export interface Configuration<M = Middleware> {
15+
readonly baseServer: BaseServerConfiguration;
16+
readonly httpApi: HttpLibrary;
17+
readonly middleware: M[];
18+
readonly authMethods: AuthMethods;
1919
}
2020

21+
// Additional option specific to middleware merge strategy
22+
export interface MiddlewareMergeOptions {
23+
// default is `'replace'` for backwards compatibility
24+
middlewareMergeStrategy?: 'replace' | 'append' | 'prepend';
25+
}
26+
27+
// Unify configuration options using Partial plus extra merge strategy
28+
export type ConfigurationOptions<M = Middleware> = Partial<Configuration<M>> & MiddlewareMergeOptions;
29+
30+
// aliases for convenience
31+
export type StandardConfigurationOptions = ConfigurationOptions<Middleware>;
32+
export type PromiseConfigurationOptions = ConfigurationOptions<PromiseMiddleware>;
2133

2234
/**
2335
* Interface with which a configuration object can be configured.
@@ -86,4 +98,4 @@ export function createConfiguration(conf: ConfigurationParameters = {}): Configu
8698
);
8799
}
88100
return configuration;
89-
}
101+
}

modules/openapi-generator/src/main/resources/typescript/index.mustache

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export * from "./auth/auth{{importFileExtension}}";
44
export * from "./models/all{{importFileExtension}}";
55
{{/models.0}}
66
export { createConfiguration } from "./configuration{{importFileExtension}}"
7-
export type { Configuration } from "./configuration{{importFileExtension}}"
7+
export type { Configuration{{^useInversify}}, ConfigurationOptions, PromiseConfigurationOptions{{/useInversify}} } from "./configuration{{importFileExtension}}"
88
export * from "./apis/exception{{importFileExtension}}";
99
export * from "./servers{{importFileExtension}}";
1010
export { RequiredError } from "./apis/baseapi{{importFileExtension}}";
@@ -13,7 +13,8 @@ export { RequiredError } from "./apis/baseapi{{importFileExtension}}";
1313
export { Middleware } from './middleware{{importFileExtension}}';
1414
{{/useRxJS}}
1515
{{^useRxJS}}
16-
export type { PromiseMiddleware as Middleware } from './middleware{{importFileExtension}}';
16+
export type { PromiseMiddleware as Middleware, Middleware as ObservableMiddleware } from './middleware{{importFileExtension}}';
17+
export { Observable } from './rxjsStub{{importFileExtension}}';
1718
{{/useRxJS}}
1819
{{#useObjectParameters}}
1920
export { {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}type {{classname}}{{operationIdCamelCase}}Request, {{/operation}}Object{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/ObjectParamAPI{{importFileExtension}}';

modules/openapi-generator/src/main/resources/typescript/services/ObservableAPI.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { HttpFile } from "../http/http";
22
import type { Observable } from {{#useRxJS}}"rxjs"{{/useRxJS}}{{^useRxJS}}"../rxjsStub"{{/useRxJS}};
3-
import type { Configuration } from "../configuration";
3+
import type { Configuration{{^useInversify}}Options{{/useInversify}} } from "../configuration";
44

55
{{#models}}
66
{{#model}}
@@ -14,10 +14,10 @@ import { {{{ classname }}} } from "{{{ importPath }}}";
1414

1515
export abstract class AbstractObservable{{classname}} {
1616
{{#operation}}
17-
public abstract {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: Configuration): Observable<{{{returnType}}}{{^returnType}}void{{/returnType}}>;
17+
public abstract {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: Configuration{{^useInversify}}Options{{/useInversify}}): Observable<{{{returnType}}}{{^returnType}}void{{/returnType}}>;
1818

1919
{{/operation}}
2020
}
2121
{{/operations}}
2222
{{/apis}}
23-
{{/apiInfo}}
23+
{{/apiInfo}}

modules/openapi-generator/src/main/resources/typescript/types/ObjectParamAPI.mustache

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { ResponseContext, RequestContext, HttpFile, HttpInfo } from '../http/http{{importFileExtension}}';
2-
import { Configuration} from '../configuration{{importFileExtension}}'
2+
import { Configuration{{^useInversify}}, ConfigurationOptions{{/useInversify}} } from '../configuration{{importFileExtension}}'
3+
{{^useInversify}}
4+
import type { Middleware } from "../middleware";
5+
{{/useInversify}}
36
{{#useRxJS}}
47
import { Observable } from 'rxjs';
58
{{/useRxJS}}
@@ -55,7 +58,7 @@ export class Object{{classname}} {
5558
{{/summary}}
5659
* @param param the request object
5760
*/
58-
public {{nickname}}WithHttpInfo(param: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, options?: Configuration): {{#useRxJS}}Observable{{/useRxJS}}{{^useRxJS}}Promise{{/useRxJS}}<HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
61+
public {{nickname}}WithHttpInfo(param: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, options?: Configuration{{^useInversify}}Options{{/useInversify}}): {{#useRxJS}}Observable{{/useRxJS}}{{^useRxJS}}Promise{{/useRxJS}}<HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
5962
return this.api.{{nickname}}WithHttpInfo({{#allParams}}param.{{paramName}}, {{/allParams}} options){{^useRxJS}}.toPromise(){{/useRxJS}};
6063
}
6164

@@ -68,7 +71,7 @@ export class Object{{classname}} {
6871
{{/summary}}
6972
* @param param the request object
7073
*/
71-
public {{nickname}}(param: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, options?: Configuration): {{#useRxJS}}Observable{{/useRxJS}}{{^useRxJS}}Promise{{/useRxJS}}<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
74+
public {{nickname}}(param: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, options?: Configuration{{^useInversify}}Options{{/useInversify}}): {{#useRxJS}}Observable{{/useRxJS}}{{^useRxJS}}Promise{{/useRxJS}}<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
7275
return this.api.{{nickname}}({{#allParams}}param.{{paramName}}, {{/allParams}} options){{^useRxJS}}.toPromise(){{/useRxJS}};
7376
}
7477

modules/openapi-generator/src/main/resources/typescript/types/ObservableAPI.mustache

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ResponseContext, RequestContext, HttpFile, HttpInfo } from '../http/http{{importFileExtension}}';
2-
import { Configuration} from '../configuration{{importFileExtension}}'
2+
import { Configuration{{^useInversify}}, ConfigurationOptions{{/useInversify}} } from '../configuration{{importFileExtension}}'
3+
import type { Middleware } from "../middleware";
34
import { Observable, of, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{importFileExtension}}'{{/useRxJS}};
45
import {mergeMap, map} from {{#useRxJS}}'rxjs/operators'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{importFileExtension}}'{{/useRxJS}};
56
{{#useInversify}}
@@ -61,19 +62,56 @@ export class Observable{{classname}} {
6162
* @param {{#required}}{{paramName}}{{/required}}{{^required}}[{{paramName}}]{{/required}}{{#description}} {{description}}{{/description}}
6263
{{/allParams}}
6364
*/
64-
public {{nickname}}WithHttpInfo({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: Configuration): Observable<HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
65-
const requestContextPromise = this.requestFactory.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}_options);
65+
public {{nickname}}WithHttpInfo({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: Configuration{{^useInversify}}Options{{/useInversify}}): Observable<HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
66+
let _config = this.configuration;
67+
let allMiddleware: Middleware[] = [];
68+
{{#useInversify}}
69+
if (_options){
70+
_config = _options;
71+
}
72+
allMiddleware = _config?.middleware;
73+
{{/useInversify}}
74+
{{^useInversify}}
75+
if (_options && _options.middleware){
76+
const middlewareMergeStrategy = _options.middlewareMergeStrategy || 'replace' // default to replace behavior
77+
// call-time middleware provided
78+
const calltimeMiddleware: Middleware[] = _options.middleware;
79+
80+
switch(middlewareMergeStrategy){
81+
case 'append':
82+
allMiddleware = this.configuration.middleware.concat(calltimeMiddleware);
83+
break;
84+
case 'prepend':
85+
allMiddleware = calltimeMiddleware.concat(this.configuration.middleware)
86+
break;
87+
case 'replace':
88+
allMiddleware = calltimeMiddleware
89+
break;
90+
default:
91+
throw new Error(`unrecognized middleware merge strategy '${middlewareMergeStrategy}'`)
92+
}
93+
}
94+
if (_options){
95+
_config = {
96+
baseServer: _options.baseServer || this.configuration.baseServer,
97+
httpApi: _options.httpApi || this.configuration.httpApi,
98+
authMethods: _options.authMethods || this.configuration.authMethods,
99+
middleware: allMiddleware || this.configuration.middleware
100+
};
101+
}
102+
{{/useInversify}}
66103

104+
const requestContextPromise = this.requestFactory.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}{{#useInversify}}_options{{/useInversify}}{{^useInversify}}_config{{/useInversify}});
67105
// build promise chain
68106
let middlewarePreObservable = from<RequestContext>(requestContextPromise);
69-
for (const middleware of this.configuration.middleware) {
107+
for (const middleware of allMiddleware) {
70108
middlewarePreObservable = middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => middleware.pre(ctx)));
71109
}
72110

73111
return middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => this.configuration.httpApi.send(ctx))).
74112
pipe(mergeMap((response: ResponseContext) => {
75113
let middlewarePostObservable = of(response);
76-
for (const middleware of this.configuration.middleware) {
114+
for (const middleware of allMiddleware.reverse()) {
77115
middlewarePostObservable = middlewarePostObservable.pipe(mergeMap((rsp: ResponseContext) => middleware.post(rsp)));
78116
}
79117
return middlewarePostObservable.pipe(map((rsp: ResponseContext) => this.responseProcessor.{{nickname}}WithHttpInfo(rsp)));
@@ -91,7 +129,7 @@ export class Observable{{classname}} {
91129
* @param {{#required}}{{paramName}}{{/required}}{{^required}}[{{paramName}}]{{/required}}{{#description}} {{description}}{{/description}}
92130
{{/allParams}}
93131
*/
94-
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: Configuration): Observable<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
132+
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: Configuration{{^useInversify}}Options{{/useInversify}}): Observable<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
95133
return this.{{nickname}}WithHttpInfo({{#allParams}}{{paramName}}, {{/allParams}}_options).pipe(map((apiResponse: HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>) => apiResponse.data));
96134
}
97135

modules/openapi-generator/src/main/resources/typescript/types/PromiseAPI.mustache

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { ResponseContext, RequestContext, HttpFile, HttpInfo } from '../http/http{{importFileExtension}}';
2-
import { Configuration} from '../configuration{{importFileExtension}}'
2+
import { Configuration{{^useInversify}}, ConfigurationOptions, PromiseConfigurationOptions{{/useInversify}} } from '../configuration{{importFileExtension}}'
3+
{{^useInversify}}
4+
import { PromiseMiddleware, Middleware, PromiseMiddlewareWrapper } from "../middleware";
5+
{{/useInversify}}
36
{{#useInversify}}
47
import { injectable, inject, optional } from "inversify";
58
import { AbstractConfiguration } from "../services/configuration";
@@ -51,8 +54,22 @@ export class Promise{{classname}} {
5154
* @param {{#required}}{{paramName}}{{/required}}{{^required}}[{{paramName}}]{{/required}}{{#description}} {{description}}{{/description}}
5255
{{/allParams}}
5356
*/
54-
public {{nickname}}WithHttpInfo({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: Configuration): Promise<HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
55-
const result = this.api.{{nickname}}WithHttpInfo({{#allParams}}{{paramName}}, {{/allParams}}_options);
57+
public {{nickname}}WithHttpInfo({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: {{#useInversify}}Configuration{{/useInversify}}{{^useInversify}}PromiseConfigurationOptions{{/useInversify}}): Promise<HttpInfo<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
58+
let observableOptions: undefined | Configuration{{^useInversify}}Options{{/useInversify}}{{#useInversify}} = _options{{/useInversify}}
59+
{{^useInversify}}
60+
if (_options){
61+
observableOptions = {
62+
baseServer: _options.baseServer,
63+
httpApi: _options.httpApi,
64+
middleware: _options.middleware?.map(
65+
m => new PromiseMiddlewareWrapper(m)
66+
),
67+
middlewareMergeStrategy: _options.middlewareMergeStrategy,
68+
authMethods: _options.authMethods
69+
}
70+
}
71+
{{/useInversify}}
72+
const result = this.api.{{nickname}}WithHttpInfo({{#allParams}}{{paramName}}, {{/allParams}}observableOptions);
5673
return result.toPromise();
5774
}
5875

@@ -67,8 +84,22 @@ export class Promise{{classname}} {
6784
* @param {{#required}}{{paramName}}{{/required}}{{^required}}[{{paramName}}]{{/required}}{{#description}} {{description}}{{/description}}
6885
{{/allParams}}
6986
*/
70-
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: Configuration): Promise<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
71-
const result = this.api.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}_options);
87+
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}_options?: {{#useInversify}}Configuration{{/useInversify}}{{^useInversify}}PromiseConfigurationOptions{{/useInversify}}): Promise<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
88+
let observableOptions: undefined | Configuration{{^useInversify}}Options{{/useInversify}}{{#useInversify}} = _options{{/useInversify}}
89+
{{^useInversify}}
90+
if (_options){
91+
observableOptions = {
92+
baseServer: _options.baseServer,
93+
httpApi: _options.httpApi,
94+
middleware: _options.middleware?.map(
95+
m => new PromiseMiddlewareWrapper(m)
96+
),
97+
middlewareMergeStrategy: _options.middlewareMergeStrategy,
98+
authMethods: _options.authMethods
99+
}
100+
}
101+
{{/useInversify}}
102+
const result = this.api.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}observableOptions);
72103
return result.toPromise();
73104
}
74105

samples/client/others/typescript/builds/array-of-lists/apis/DefaultApi.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/array-of-lists/configuration.ts

Lines changed: 18 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/client/others/typescript/builds/array-of-lists/index.ts

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)