From 8d5c7de222bb1089c1c9651746f8a2bfea6af231 Mon Sep 17 00:00:00 2001
From: Neal Granger <neal@nealg.com>
Date: Mon, 24 Oct 2022 18:23:35 -0700
Subject: [PATCH] Fix missing imports when using allOf composition

---
 .../typescript-rxjs-allOf-composition.yaml    |   4 +
 .../TypeScriptRxjsClientCodegen.java          |   7 +
 .../allOf-composition/.gitignore              |   4 +
 .../.openapi-generator-ignore                 |  23 +++
 .../.openapi-generator/FILES                  |  15 ++
 .../.openapi-generator/VERSION                |   1 +
 .../allOf-composition/apis/DefaultApi.ts      |  44 ++++
 .../allOf-composition/apis/index.ts           |   1 +
 .../allOf-composition/index.ts                |   4 +
 .../allOf-composition/models/Hero.ts          |  30 +++
 .../allOf-composition/models/Human.ts         |  30 +++
 .../allOf-composition/models/SuperBaby.ts     |  23 +++
 .../models/SuperBabyAllOf.ts                  |  29 +++
 .../allOf-composition/models/SuperBoy.ts      |  23 +++
 .../allOf-composition/models/SuperBoyAllOf.ts |  29 +++
 .../allOf-composition/models/SuperMan.ts      |  24 +++
 .../allOf-composition/models/index.ts         |   7 +
 .../allOf-composition/runtime.ts              | 193 ++++++++++++++++++
 .../allOf-composition/servers.ts              |  43 ++++
 .../allOf-composition/tsconfig.json           |  22 ++
 20 files changed, 556 insertions(+)
 create mode 100644 bin/configs/typescript-rxjs-allOf-composition.yaml
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/.gitignore
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator-ignore
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/FILES
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/VERSION
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/apis/DefaultApi.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/apis/index.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/index.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/Hero.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/Human.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/SuperBaby.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/SuperBabyAllOf.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoy.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoyAllOf.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/SuperMan.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/models/index.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/runtime.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/servers.ts
 create mode 100644 samples/client/others/typescript-rxjs/allOf-composition/tsconfig.json

diff --git a/bin/configs/typescript-rxjs-allOf-composition.yaml b/bin/configs/typescript-rxjs-allOf-composition.yaml
new file mode 100644
index 00000000000..e9bca87aa19
--- /dev/null
+++ b/bin/configs/typescript-rxjs-allOf-composition.yaml
@@ -0,0 +1,4 @@
+generatorName: typescript-rxjs
+outputDir: samples/client/others/typescript-rxjs/allOf-composition
+inputSpec: modules/openapi-generator/src/test/resources/3_0/allOf_composition.yaml
+templateDir: modules/openapi-generator/src/main/resources/typescript-rxjs
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
index e9091517b3b..aeaca5caf3c 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptRxjsClientCodegen.java
@@ -18,6 +18,7 @@
 package org.openapitools.codegen.languages;
 
 import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.ComposedSchema;
 import io.swagger.v3.parser.util.SchemaTypeUtil;
 import org.openapitools.codegen.*;
 import org.openapitools.codegen.meta.features.DocumentationFeature;
@@ -420,4 +421,10 @@ public class TypeScriptRxjsClientCodegen extends AbstractTypeScriptClientCodegen
             this.hasOptionalQueryParams = false; // will be updated within addConditionalImportInformation
         }
     }
+
+    @Override
+    protected void addImport(ComposedSchema composed, Schema childSchema, CodegenModel model, String modelName) {
+        // import everything (including child schema of a composed schema)
+        addImport(model, modelName);
+    }
 }
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/.gitignore b/samples/client/others/typescript-rxjs/allOf-composition/.gitignore
new file mode 100644
index 00000000000..149b5765472
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/.gitignore
@@ -0,0 +1,4 @@
+wwwroot/*.js
+node_modules
+typings
+dist
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator-ignore b/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/.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/others/typescript-rxjs/allOf-composition/.openapi-generator/FILES b/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/FILES
new file mode 100644
index 00000000000..89276d499a4
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/FILES
@@ -0,0 +1,15 @@
+.gitignore
+apis/DefaultApi.ts
+apis/index.ts
+index.ts
+models/Hero.ts
+models/Human.ts
+models/SuperBaby.ts
+models/SuperBabyAllOf.ts
+models/SuperBoy.ts
+models/SuperBoyAllOf.ts
+models/SuperMan.ts
+models/index.ts
+runtime.ts
+servers.ts
+tsconfig.json
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/VERSION b/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/VERSION
new file mode 100644
index 00000000000..ed829dbcdde
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/.openapi-generator/VERSION
@@ -0,0 +1 @@
+6.2.1-SNAPSHOT
\ No newline at end of file
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/apis/DefaultApi.ts b/samples/client/others/typescript-rxjs/allOf-composition/apis/DefaultApi.ts
new file mode 100644
index 00000000000..50216e7be70
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/apis/DefaultApi.ts
@@ -0,0 +1,44 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+import type { Observable } from 'rxjs';
+import type { AjaxResponse } from 'rxjs/ajax';
+import { BaseAPI, throwIfNullOrUndefined, encodeURI } from '../runtime';
+import type { OperationOpts } from '../runtime';
+import type {
+    SuperMan,
+} from '../models';
+
+export interface ListRequest {
+    personId: string;
+}
+
+/**
+ * no description
+ */
+export class DefaultApi extends BaseAPI {
+
+    /**
+     */
+    list({ personId }: ListRequest): Observable<SuperMan>
+    list({ personId }: ListRequest, opts?: OperationOpts): Observable<AjaxResponse<SuperMan>>
+    list({ personId }: ListRequest, opts?: OperationOpts): Observable<SuperMan | AjaxResponse<SuperMan>> {
+        throwIfNullOrUndefined(personId, 'personId', 'list');
+
+        return this.request<SuperMan>({
+            url: '/person/display/{personId}'.replace('{personId}', encodeURI(personId)),
+            method: 'GET',
+        }, opts?.responseOpts);
+    };
+
+}
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/apis/index.ts b/samples/client/others/typescript-rxjs/allOf-composition/apis/index.ts
new file mode 100644
index 00000000000..a1aa4698ff2
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/apis/index.ts
@@ -0,0 +1 @@
+export * from './DefaultApi';
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/index.ts b/samples/client/others/typescript-rxjs/allOf-composition/index.ts
new file mode 100644
index 00000000000..b9e2f3ca3b7
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/index.ts
@@ -0,0 +1,4 @@
+export * from './runtime';
+export * from './servers';
+export * from './apis';
+export * from './models';
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/Hero.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/Hero.ts
new file mode 100644
index 00000000000..98c39a6ecd6
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/Hero.ts
@@ -0,0 +1,30 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+/**
+ * Hero
+ * @export
+ * @interface Hero
+ */
+export interface Hero {
+    /**
+     * @type {number}
+     * @memberof Hero
+     */
+    reward?: number;
+    /**
+     * @type {string}
+     * @memberof Hero
+     */
+    origin: string;
+}
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/Human.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/Human.ts
new file mode 100644
index 00000000000..2122f4c7a13
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/Human.ts
@@ -0,0 +1,30 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+/**
+ * Human
+ * @export
+ * @interface Human
+ */
+export interface Human {
+    /**
+     * @type {number}
+     * @memberof Human
+     */
+    id: number;
+    /**
+     * @type {string}
+     * @memberof Human
+     */
+    name?: string;
+}
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBaby.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBaby.ts
new file mode 100644
index 00000000000..1647f9aa201
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBaby.ts
@@ -0,0 +1,23 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+import type {
+    Human,
+    SuperBabyAllOf,
+} from './';
+
+/**
+ * @type SuperBaby
+ * @export
+ */
+export type SuperBaby = Human & SuperBabyAllOf;
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBabyAllOf.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBabyAllOf.ts
new file mode 100644
index 00000000000..459c28d0f4e
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBabyAllOf.ts
@@ -0,0 +1,29 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+/**
+ * @export
+ * @interface SuperBabyAllOf
+ */
+export interface SuperBabyAllOf {
+    /**
+     * @type {string}
+     * @memberof SuperBabyAllOf
+     */
+    gender?: string;
+    /**
+     * @type {number}
+     * @memberof SuperBabyAllOf
+     */
+    age?: number;
+}
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoy.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoy.ts
new file mode 100644
index 00000000000..668faac8d17
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoy.ts
@@ -0,0 +1,23 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+import type {
+    Human,
+    SuperBoyAllOf,
+} from './';
+
+/**
+ * @type SuperBoy
+ * @export
+ */
+export type SuperBoy = Human & SuperBoyAllOf;
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoyAllOf.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoyAllOf.ts
new file mode 100644
index 00000000000..26003b90c7d
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperBoyAllOf.ts
@@ -0,0 +1,29 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+/**
+ * @export
+ * @interface SuperBoyAllOf
+ */
+export interface SuperBoyAllOf {
+    /**
+     * @type {string}
+     * @memberof SuperBoyAllOf
+     */
+    category?: string;
+    /**
+     * @type {number}
+     * @memberof SuperBoyAllOf
+     */
+    level: number;
+}
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/SuperMan.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperMan.ts
new file mode 100644
index 00000000000..8548fb03519
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/SuperMan.ts
@@ -0,0 +1,24 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+import type {
+    Hero,
+    Human,
+    SuperBoyAllOf,
+} from './';
+
+/**
+ * @type SuperMan
+ * @export
+ */
+export type SuperMan = Hero & Human & SuperBoyAllOf;
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/models/index.ts b/samples/client/others/typescript-rxjs/allOf-composition/models/index.ts
new file mode 100644
index 00000000000..d57bd6be7b9
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/models/index.ts
@@ -0,0 +1,7 @@
+export * from './Hero';
+export * from './Human';
+export * from './SuperBaby';
+export * from './SuperBabyAllOf';
+export * from './SuperBoy';
+export * from './SuperBoyAllOf';
+export * from './SuperMan';
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/runtime.ts b/samples/client/others/typescript-rxjs/allOf-composition/runtime.ts
new file mode 100644
index 00000000000..64b0b2b4ad4
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/runtime.ts
@@ -0,0 +1,193 @@
+// tslint:disable
+/**
+ * Example
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * 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.
+ */
+
+import { of } from 'rxjs';
+import type { Observable } from 'rxjs';
+import { ajax } from 'rxjs/ajax';
+import type { AjaxConfig, AjaxResponse } from 'rxjs/ajax';
+import { map, concatMap } from 'rxjs/operators';
+import { servers } from './servers';
+
+export const BASE_PATH = servers[0].getUrl();
+
+export interface ConfigurationParameters {
+    basePath?: string; // override base path
+    middleware?: Middleware[]; // middleware to apply before/after rxjs requests
+    username?: string; // parameter for basic security
+    password?: string; // parameter for basic security
+    apiKey?: string | ((name: string) => string); // parameter for apiKey security
+    accessToken?: string | ((name?: string, scopes?: string[]) => string); // parameter for oauth2 security
+}
+
+export class Configuration {
+    constructor(private configuration: ConfigurationParameters = {}) {}
+
+    get basePath(): string {
+        return this.configuration.basePath ?? BASE_PATH;
+    }
+
+    get middleware(): Middleware[] {
+        return this.configuration.middleware ?? [];
+    }
+
+    get username(): string | undefined {
+        return this.configuration.username;
+    }
+
+    get password(): string | undefined {
+        return this.configuration.password;
+    }
+
+    get apiKey(): ((name: string) => string) | undefined {
+        const { apiKey } = this.configuration;
+        return apiKey ? (typeof apiKey === 'string' ? () => apiKey : apiKey) : undefined;
+    }
+
+    get accessToken(): ((name: string, scopes?: string[]) => string) | undefined {
+        const { accessToken } = this.configuration;
+        return accessToken ? (typeof accessToken === 'string' ? () => accessToken : accessToken) : undefined;
+    }
+}
+
+/**
+ * This is the base class for all generated API classes.
+ */
+export class BaseAPI {
+    private middleware: Middleware[] = [];
+
+    constructor(protected configuration = new Configuration()) {
+        this.middleware = configuration.middleware;
+    }
+
+    withMiddleware = (middlewares: Middleware[]): this => {
+        const next = this.clone();
+        next.middleware = next.middleware.concat(middlewares);
+        return next;
+    };
+
+    withPreMiddleware = (preMiddlewares: Array<Middleware['pre']>) =>
+        this.withMiddleware(preMiddlewares.map((pre) => ({ pre })));
+
+    withPostMiddleware = (postMiddlewares: Array<Middleware['post']>) =>
+        this.withMiddleware(postMiddlewares.map((post) => ({ post })));
+
+    protected request<T>(requestOpts: RequestOpts): Observable<T>
+    protected request<T>(requestOpts: RequestOpts, responseOpts?: ResponseOpts): Observable<AjaxResponse<T>>
+    protected request<T>(requestOpts: RequestOpts, responseOpts?: ResponseOpts): Observable<T | AjaxResponse<T>> {
+        return this.rxjsRequest<T>(this.createRequestArgs(requestOpts)).pipe(
+            map((res) => {
+                const { status, response } = res;
+                if (status >= 200 && status < 300) {
+                    return responseOpts?.response === 'raw' ? res : response;
+                }
+                throw res;
+            })
+        );
+    }
+
+    private createRequestArgs = ({ url: baseUrl, query, method, headers, body, responseType }: RequestOpts): AjaxConfig => {
+        // only add the queryString to the URL if there are query parameters.
+        // this is done to avoid urls ending with a '?' character which buggy webservers
+        // do not handle correctly sometimes.
+        const url = `${this.configuration.basePath}${baseUrl}${query && Object.keys(query).length ? `?${queryString(query)}`: ''}`;
+
+        return {
+            url,
+            method,
+            headers,
+            body: body instanceof FormData ? body : JSON.stringify(body),
+            responseType: responseType ?? 'json',
+        };
+    }
+
+    private rxjsRequest = <T>(params: AjaxConfig): Observable<AjaxResponse<T>> =>
+        of(params).pipe(
+            map((request) => {
+                this.middleware.filter((item) => item.pre).forEach((mw) => (request = mw.pre!(request)));
+                return request;
+            }),
+            concatMap((args) =>
+                ajax<T>(args).pipe(
+                    map((response) => {
+                        this.middleware.filter((item) => item.post).forEach((mw) => (response = mw.post!(response)));
+                        return response;
+                    })
+                )
+            )
+        );
+
+    /**
+     * Create a shallow clone of `this` by constructing a new instance
+     * and then shallow cloning data members.
+     */
+    private clone = (): this =>
+        Object.assign(Object.create(Object.getPrototypeOf(this)), this);
+}
+
+/**
+ * @deprecated
+ * export for not being a breaking change
+ */
+export class RequiredError extends Error {
+    override name: 'RequiredError' = 'RequiredError';
+}
+
+export const COLLECTION_FORMATS = {
+    csv: ',',
+    ssv: ' ',
+    tsv: '\t',
+    pipes: '|',
+};
+
+export type Json = any;
+export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
+export type HttpHeaders = { [key: string]: string };
+export type HttpQuery = Partial<{ [key: string]: string | number | null | boolean | Array<string | number | null | boolean> }>; // partial is needed for strict mode
+export type HttpBody = Json | FormData;
+
+export interface RequestOpts extends AjaxConfig {
+    // TODO: replace custom 'query' prop with 'queryParams'
+    query?: HttpQuery; // additional prop
+    // the following props have improved types over AjaxRequest
+    method: HttpMethod;
+    headers?: HttpHeaders;
+    body?: HttpBody;
+}
+
+export interface ResponseOpts {
+    response?: 'raw';
+}
+
+export interface OperationOpts {
+    responseOpts?: ResponseOpts;
+}
+
+export const encodeURI = (value: any) => encodeURIComponent(`${value}`);
+
+const queryString = (params: HttpQuery): string => Object.entries(params)
+    .map(([key, value]) => value instanceof Array
+        ? value.map((val) => `${encodeURI(key)}=${encodeURI(val)}`).join('&')
+        : `${encodeURI(key)}=${encodeURI(value)}`
+    )
+    .join('&');
+
+export const throwIfNullOrUndefined = (value: any, paramName: string, nickname: string) => {
+    if (value == null) {
+        throw new Error(`Parameter "${paramName}" was null or undefined when calling "${nickname}".`);
+    }
+};
+
+export interface Middleware {
+    pre?(request: AjaxConfig): AjaxConfig;
+    post?(response: AjaxResponse<any>): AjaxResponse<any>;
+}
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/servers.ts b/samples/client/others/typescript-rxjs/allOf-composition/servers.ts
new file mode 100644
index 00000000000..3d22265d43f
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/servers.ts
@@ -0,0 +1,43 @@
+/**
+ *
+ * Represents the configuration of a server including its
+ * url template and variable configuration based on the url.
+ *
+ */
+export class ServerConfiguration<T extends { [key: string]: string }> {
+    public constructor(private url: string, private variableConfiguration: T, private description: string) {}
+
+    /**
+     * Sets the value of the variables of this server.
+     *
+     * @param variableConfiguration a partial variable configuration for the variables contained in the url
+     */
+    public setVariables(variableConfiguration: Partial<T>) {
+        Object.assign(this.variableConfiguration, variableConfiguration);
+    }
+
+    public getConfiguration(): T {
+        return this.variableConfiguration;
+    }
+
+    public getDescription(): string {
+        return this.description;
+    }
+
+    /**
+     * Constructions the URL this server using the url with variables
+     * replaced with their respective values
+     */
+    public getUrl(): string {
+        let replacedUrl = this.url;
+        for (const key in this.variableConfiguration) {
+            var re = new RegExp("{" + key + "}","g");
+            replacedUrl = replacedUrl.replace(re, this.variableConfiguration[key]);
+        }
+        return replacedUrl;
+    }
+}
+
+const server1 = new ServerConfiguration<{  }>("http://api.example.xyz/v1", {  }, "");
+
+export const servers = [server1];
diff --git a/samples/client/others/typescript-rxjs/allOf-composition/tsconfig.json b/samples/client/others/typescript-rxjs/allOf-composition/tsconfig.json
new file mode 100644
index 00000000000..59a60838a05
--- /dev/null
+++ b/samples/client/others/typescript-rxjs/allOf-composition/tsconfig.json
@@ -0,0 +1,22 @@
+{
+  "compilerOptions": {
+    "declaration": true,
+    "target": "es5",
+    "module": "commonjs",
+    "moduleResolution": "node",
+    "outDir": "dist",
+    "rootDir": ".",
+    "lib": [
+      "es6",
+      "dom",
+      "es2017"
+    ],
+    "typeRoots": [
+      "node_modules/@types"
+    ]
+  },
+  "exclude": [
+    "dist",
+    "node_modules"
+  ]
+}
-- 
GitLab