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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -787,21 +787,26 @@ private ExtendedCodegenModel processCodeGenModel(ExtendedCodegenModel cm) {
.map(CodegenComposedSchemas::getOneOf)
.orElse(Collections.emptyList());

// create a set of any non-primitive, non-array types used in the oneOf schemas which will
// need to be imported.
cm.oneOfModels = oneOfsList.stream()
.filter(CodegenProperty::getIsModel)
.filter(cp -> !cp.getIsPrimitiveType() && !cp.getIsArray())
.map(CodegenProperty::getBaseType)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(TreeSet::new));

// create a set of any complex, inner types used by arrays in the oneOf schema (e.g. if
// the oneOf uses Array<Foo>, Foo needs to be imported).
cm.oneOfArrays = oneOfsList.stream()
.filter(CodegenProperty::getIsArray)
.map(CodegenProperty::getComplexType)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(TreeSet::new));

// create a set of primitive types used in the oneOf schemas for use in the to & from
// typed JSON methods.
cm.oneOfPrimitives = oneOfsList.stream()
.filter(CodegenProperty::getIsPrimitiveType)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(HashSet::new));

if (!cm.oneOf.isEmpty()) {
Expand Down Expand Up @@ -1485,6 +1490,9 @@ public class ExtendedCodegenModel extends CodegenModel {
@Getter @Setter
public Set<String> modelImports = new TreeSet<String>();

// oneOfModels, oneOfArrays & oneOfPrimitives contain a list of types used in schemas
// composed with oneOf and are used to define the import list and the to & from
// 'TypedJSON' conversion methods in the composed model classes.
@Getter @Setter
public Set<String> oneOfModels = new TreeSet<>();
@Getter @Setter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import java.util.Collections;
import java.util.Locale;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.config.CodegenConfigurator;
Expand Down Expand Up @@ -404,6 +406,44 @@ public void testOneOfModelsDoNotImportPrimitiveTypes() throws IOException {
TestUtils.assertFileContains(testDiscriminatorResponse, "export type TestDiscriminatorResponse = { discriminatorField: 'optionOne' } & OptionOne | { discriminatorField: 'optionTwo' } & OptionTwo");
}

/**
* Issue #21587
* When using oneOf, the Typescript Fetch generator should import modelled types except for
* types built-in primitive types, even those marked with additional properties.
*/
@Test()
public void testOneOfModelsImportNonPrimitiveTypes() throws IOException {
File output = generate(
Collections.emptyMap(),
"src/test/resources/3_0/typescript-fetch/issue_21587.yaml"
);

Path testResponse = Paths.get(output + "/models/OneOfResponse.ts");
TestUtils.assertFileExists(testResponse);

// Primitive built-in types should not be included. This list is based off the type mappings
// and language specific primitive keywords established in the AbstractTypeScriptClientCodegen
Stream.of(
"Set",
"Array",
"boolean",
"string",
"number",
"object",
"any",
"Date",
"Error"
).forEach(primitiveType ->
TestUtils.assertFileNotContains(
testResponse,
String.format(Locale.ROOT, "import type { %s } from './%s'", primitiveType, primitiveType)
)
);
TestUtils.assertFileContains(testResponse, "import type { OptionOne } from './OptionOne'");
TestUtils.assertFileContains(testResponse, "import type { OptionTwo } from './OptionTwo'");
TestUtils.assertFileContains(testResponse, "import type { OptionThree } from './OptionThree'");
}

private static File generate(
Map<String, Object> properties
) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
openapi: 3.0.1
info:
title: Example API
version: 1.0.0
paths:
/api/endpoint:
get:
operationId: GetEndpoint
summary: Get endpoint
tags:
- Examples
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
title: OneOfResponse
oneOf:
- $ref: '#/components/schemas/OptionOne'
- $ref: '#/components/schemas/OptionTwo'
- type: array
items:
$ref: '#/components/schemas/OptionThree'
- type: string
enum:
- "fixed-value-a"
- "fixed-value-b"
- "fixed-value-c"
- type: boolean
- type: number
- type: string
format: date
- type: string
format: date-time
- type: integer
format: int64
enum: [10, 20, 30]
- type: array
items:
type: number
- type: array
items:
type: object
- type: array
items:
type: string
enum:
- "oneof-array-enum-a"
- "oneof-array-enum-b"
- "oneof-array-enum-c"
- type: array
items:
type: number
uniqueItems: true

components:
schemas:
OptionOne:
type: object
title: OptionOne
properties:
propOne:
type: number
additionalProperties: true
OptionTwo:
type: object
title: OptionTwo
properties:
propTwo:
type: string
OptionThree:
type: object
title: OptionThree
properties:
propThree:
type: boolean
additionalProperties: true
Loading