From a850b507a500bbade47598348b9c75eb6f8955ee Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 12:25:58 +0200 Subject: [PATCH 01/11] feat(core): add splitOperationsByContentType option to divide operations by content-type (#6708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAPI lets a single operation expose several request/response content-types with different schemas, but generators keep only the first one ("Multiple schemas found in the OAS 'content' section, returning only the first"). This yields a single, mistyped method and makes the other content-types unusable. Add an opt-in option `splitOperationsByContentType` (default false) that divides such an operation into one operation per content-type — the cartesian product of the request-body and success-response content-types (deduplicated by schema). The division happens at the spec level in DefaultCodegen#preprocessOpenAPI. Each variant is a narrowed swagger Operation (single content-type on each axis) with a typed, collision-free operationId (request -> "With", response -> "As", e.g. createReportWithXmlAsPdf). Variants are stored on the original operation under the "x-content-type-variants" extension and expanded by DefaultGenerator#processOperation, so every variant re-enters fromOperation and is typed natively by the target generator. The feature is therefore language-neutral: no per-language type re-derivation, no template change. Tested in DefaultCodegenTest for both the request×response cartesian (4 variants) and the response-only case (2 variants), and that unambiguous operations are left untouched. --- .../openapitools/codegen/DefaultCodegen.java | 234 ++++++++++++++++++ .../codegen/DefaultGenerator.java | 12 + .../codegen/DefaultCodegenTest.java | 45 ++++ .../3_0/issue6708-split-by-content-type.yaml | 70 ++++++ 4 files changed, 361 insertions(+) create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index d000cde76814..826991b97fdd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -419,6 +419,7 @@ public void processOpts() { convertPropertyToBooleanAndWriteBack(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, this::setPrependFormOrBodyParameters); convertPropertyToBooleanAndWriteBack(CodegenConstants.ENSURE_UNIQUE_PARAMS, this::setEnsureUniqueParams); convertPropertyToBooleanAndWriteBack(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, this::setAllowUnicodeIdentifiers); + convertPropertyToBooleanAndWriteBack(SPLIT_OPERATIONS_BY_CONTENT_TYPE, this::setSplitOperationsByContentType); convertPropertyToStringAndWriteBack(CodegenConstants.API_NAME_PREFIX, this::setApiNamePrefix); convertPropertyToStringAndWriteBack(CodegenConstants.API_NAME_SUFFIX, this::setApiNameSuffix); convertPropertyToStringAndWriteBack(CodegenConstants.MODEL_NAME_PREFIX, this::setModelNamePrefix); @@ -1057,10 +1058,239 @@ public void postProcessResponseWithProperty(CodegenResponse response, CodegenPro public void postProcessParameter(CodegenParameter parameter) { } + /** Opt-in option key: split operations that expose several request/response content-types. */ + public static final String SPLIT_OPERATIONS_BY_CONTENT_TYPE = "splitOperationsByContentType"; + + /** Internal vendor extension carrying the {@code List} a divided operation expands to. */ + public static final String X_CONTENT_TYPE_VARIANTS = "x-content-type-variants"; + + protected boolean splitOperationsByContentType = false; + + public void setSplitOperationsByContentType(boolean splitOperationsByContentType) { + this.splitOperationsByContentType = splitOperationsByContentType; + } + + /** + * When {@link #SPLIT_OPERATIONS_BY_CONTENT_TYPE} is enabled, divides every operation whose request + * body and/or success response expose several content-types with different schemas into one + * operation per content-type (the cartesian product of the request and response axes). The variants + * are stored on the original {@link Operation} under {@link #X_CONTENT_TYPE_VARIANTS} and expanded by + * {@code DefaultGenerator}, so each one re-enters {@code fromOperation} and is typed natively by the + * target generator. This keeps the feature language-neutral: no per-language type re-derivation here. + */ + private void divideOperationsByContentType(OpenAPI openAPI) { + if (!splitOperationsByContentType || openAPI.getPaths() == null) { + return; + } + for (Map.Entry pathEntry : openAPI.getPaths().entrySet()) { + String path = pathEntry.getKey(); + for (Map.Entry opEntry : pathEntry.getValue().readOperationsMap().entrySet()) { + divideOperationByContentType(openAPI, path, opEntry.getKey().name().toLowerCase(Locale.ROOT), opEntry.getValue()); + } + } + } + + private void divideOperationByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { + List requestAxis = requestContentTypeAxis(openAPI, operation); + String targetResponseCode = findMultiSchemaSuccessResponseCode(openAPI, operation); + ApiResponse targetResponse = targetResponseCode == null ? null + : ModelUtils.getReferencedApiResponse(openAPI, operation.getResponses().get(targetResponseCode)); + List responseAxis = axisOf(targetResponse == null ? null : targetResponse.getContent()); + + boolean requestSplit = requestAxis.size() > 1; + boolean responseSplit = responseAxis.size() > 1; + if (!requestSplit && !responseSplit) { + return; // single content-type on both axes: nothing to divide + } + + String baseId = getOrGenerateOperationId(operation, path, httpMethod); + List variants = new ArrayList<>(requestAxis.size() * responseAxis.size()); + for (String requestMediaType : requestAxis) { + for (String responseMediaType : responseAxis) { + variants.add(buildOperationVariant(openAPI, operation, baseId, + requestSplit ? requestMediaType : null, + responseSplit ? responseMediaType : null, + targetResponseCode, targetResponse)); + } + } + operation.addExtension(X_CONTENT_TYPE_VARIANTS, variants); + } + + /** Distinct (by resolved schema) request-body content-types, JSON first; a singleton list if not split. */ + private List requestContentTypeAxis(OpenAPI openAPI, Operation operation) { + RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); + return axisOf(requestBody == null ? null : requestBody.getContent()); + } + + /** + * The media-types of {@code content} deduplicated by resolved schema (so two media-types mapping to + * the same schema collapse), JSON-first for determinism. Returns a singleton {@code [null]} when there + * are fewer than two distinct schemas, meaning "do not split this axis". + */ + private List axisOf(Content content) { + if (content == null || content.size() < 2) { + return Collections.singletonList(null); + } + List kept = new ArrayList<>(); + Set seenSchemas = new LinkedHashSet<>(); + for (Map.Entry entry : content.entrySet()) { + String key = schemaKey(entry.getValue() == null ? null : entry.getValue().getSchema()); + if (seenSchemas.add(key)) { + kept.add(entry.getKey()); + } + } + if (kept.size() < 2) { + return Collections.singletonList(null); + } + String preferred = kept.stream().filter(mt -> isJsonMimeType(mt)).findFirst().orElse(kept.get(0)); + List ordered = new ArrayList<>(kept.size()); + ordered.add(preferred); + for (String mediaType : kept) { + if (!mediaType.equals(preferred)) { + ordered.add(mediaType); + } + } + return ordered; + } + + /** First 2xx response exposing at least two content-types with different schemas, or {@code null}. */ + private String findMultiSchemaSuccessResponseCode(OpenAPI openAPI, Operation operation) { + if (operation.getResponses() == null) { + return null; + } + for (Map.Entry entry : operation.getResponses().entrySet()) { + String code = entry.getKey(); + if (code == null || code.length() != 3 || code.charAt(0) != '2') { + continue; + } + ApiResponse response = ModelUtils.getReferencedApiResponse(openAPI, entry.getValue()); + Content content = response == null ? null : response.getContent(); + if (content == null || content.size() < 2) { + continue; + } + long distinct = content.values().stream() + .map(mt -> schemaKey(mt == null ? null : mt.getSchema())) + .distinct().count(); + if (distinct >= 2) { + return code; + } + } + return null; + } + + /** + * Builds one operation variant narrowed to a single request and/or response media-type (a {@code null} + * media-type leaves that axis untouched), with a typed, collision-free operationId. + */ + private Operation buildOperationVariant(OpenAPI openAPI, Operation original, String baseId, String requestMediaType, + String responseMediaType, String targetResponseCode, ApiResponse targetResponse) { + Operation variant = shallowCopyOperation(original); + + // typed, collision-free operationId: request -> "With", response -> "As" + StringBuilder operationId = new StringBuilder(baseId); + if (requestMediaType != null) { + operationId.append("With").append(camelize(subtypeToken(requestMediaType))); + } + if (responseMediaType != null) { + operationId.append("As").append(camelize(subtypeToken(responseMediaType))); + } + variant.setOperationId(operationId.toString()); + + if (requestMediaType != null) { + RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, original.getRequestBody()); + variant.setRequestBody(narrowRequestBody(requestBody, requestMediaType)); + } + if (responseMediaType != null) { + variant.setResponses(narrowResponses(original.getResponses(), targetResponseCode, targetResponse, responseMediaType)); + } + return variant; + } + + /** Shallow-copies an {@link Operation}, giving the copy its own mutable parameter/extension lists. */ + private Operation shallowCopyOperation(Operation source) { + Operation copy = new Operation(); + copy.setTags(source.getTags()); + copy.setSummary(source.getSummary()); + copy.setDescription(source.getDescription()); + copy.setExternalDocs(source.getExternalDocs()); + copy.setOperationId(source.getOperationId()); + copy.setParameters(source.getParameters() == null ? null : new ArrayList<>(source.getParameters())); + copy.setRequestBody(source.getRequestBody()); + copy.setResponses(source.getResponses()); + copy.setCallbacks(source.getCallbacks()); + copy.setDeprecated(source.getDeprecated()); + copy.setSecurity(source.getSecurity() == null ? null : new ArrayList<>(source.getSecurity())); + copy.setServers(source.getServers()); + // Keep a non-null extensions map: generators (e.g. SpringCodegen) read it without null-guards. + copy.setExtensions(source.getExtensions() == null ? new LinkedHashMap<>() : new LinkedHashMap<>(source.getExtensions())); + return copy; + } + + private RequestBody narrowRequestBody(RequestBody source, String mediaType) { + RequestBody copy = new RequestBody(); + copy.setDescription(source.getDescription()); + copy.setRequired(source.getRequired()); + copy.setExtensions(source.getExtensions()); + Content content = new Content(); + content.addMediaType(mediaType, source.getContent().get(mediaType)); + copy.setContent(content); + return copy; + } + + private ApiResponses narrowResponses(ApiResponses responses, String targetCode, ApiResponse targetResponse, String mediaType) { + ApiResponses copy = new ApiResponses(); + copy.setExtensions(responses.getExtensions()); + for (Map.Entry entry : responses.entrySet()) { + if (entry.getKey().equals(targetCode)) { + copy.addApiResponse(entry.getKey(), narrowApiResponse(targetResponse, mediaType)); + } else { + copy.addApiResponse(entry.getKey(), entry.getValue()); + } + } + return copy; + } + + private ApiResponse narrowApiResponse(ApiResponse source, String mediaType) { + ApiResponse copy = new ApiResponse(); + copy.setDescription(source.getDescription()); + copy.setHeaders(source.getHeaders()); + copy.setLinks(source.getLinks()); + copy.setExtensions(source.getExtensions()); + Content content = new Content(); + content.addMediaType(mediaType, source.getContent().get(mediaType)); + copy.setContent(content); + return copy; + } + + /** Stable identity key for a schema: its {@code $ref} when present, else a structural key. */ + private static String schemaKey(Schema schema) { + if (schema == null) { + return "null"; + } + if (schema.get$ref() != null) { + return schema.get$ref(); + } + StringBuilder key = new StringBuilder(); + key.append(schema.getType()).append('|').append(schema.getFormat()); + if (schema.getItems() != null) { + key.append("|items=").append(schemaKey(schema.getItems())); + } + return key.toString(); + } + + /** Token derived from a media-type subtype, e.g. {@code Directlog} from {@code application/directlog}. */ + private static String subtypeToken(String mediaType) { + String subtype = mediaType.substring(mediaType.indexOf('/') + 1); + subtype = subtype.replaceAll("\\+.*$", ""); // drop structured suffix (+json, +xml, ...) + subtype = subtype.replaceAll("[^a-zA-Z0-9]+", "_"); + return subtype; + } + //override with any special handling of the entire OpenAPI spec document @Override @SuppressWarnings("unused") public void preprocessOpenAPI(OpenAPI openAPI) { + divideOperationsByContentType(openAPI); if (useOneOfInterfaces && openAPI.getComponents() != null) { // we process the openapi schema here to find oneOf schemas and create interface models for them Map schemas = new HashMap<>(openAPI.getComponents().getSchemas()); @@ -1831,6 +2061,10 @@ public DefaultCodegen() { // option to change the order of form/body parameter cliOptions.add(CliOption.newBoolean(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS_DESC).defaultValue(Boolean.FALSE.toString())); + // option to split operations that expose several request/response content-types with different schemas + cliOptions.add(CliOption.newBoolean(SPLIT_OPERATIONS_BY_CONTENT_TYPE, + "Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.") + .defaultValue(Boolean.FALSE.toString())); // option to change how we process + set the data in the discriminator mapping CliOption legacyDiscriminatorBehaviorOpt = CliOption.newBoolean(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR_DESC).defaultValue(Boolean.TRUE.toString()); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java index 60b17e8e47d5..eea6d8639e28 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java @@ -1521,6 +1521,18 @@ private void processOperation(String resourcePath, String httpMethod, Operation return; } + // splitOperationsByContentType: an operation divided by content-type expands into its variants, + // each a self-contained single-content-type Operation that re-enters the normal pipeline. + if (operation.getExtensions() != null) { + Object variants = operation.getExtensions().get(DefaultCodegen.X_CONTENT_TYPE_VARIANTS); + if (variants instanceof List && !((List) variants).isEmpty()) { + for (Object variant : (List) variants) { + processOperation(resourcePath, httpMethod, (Operation) variant, operations, path); + } + return; + } + } + if (GlobalSettings.getProperty("debugOperations") != null) { LOGGER.info("processOperation: resourcePath= {}\t;{} {}\n", resourcePath, httpMethod, operation); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index afd75b3f16f6..c3d30fe441cd 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -5224,4 +5224,49 @@ private List getNames(List props) { if (props == null) return null; return props.stream().map(v -> v.name).collect(Collectors.toList()); } + + @Test + public void splitOperationsByContentType() { + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setSplitOperationsByContentType(true); + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/issue6708-split-by-content-type.yaml"); + + codegen.preprocessOpenAPI(openAPI); + + // POST /reports: request {json -> Report, xml -> ReportXml} x response {json -> Receipt, pdf -> binary} + // is divided into the cartesian product, each variant narrowed to a single content-type on both axes. + List postVariants = contentTypeVariants(openAPI.getPaths().get("/reports").getPost()); + assertThat(postVariants).extracting(Operation::getOperationId) + .containsExactlyInAnyOrder("createReportWithJsonAsJson", "createReportWithJsonAsPdf", + "createReportWithXmlAsJson", "createReportWithXmlAsPdf"); + for (Operation variant : postVariants) { + assertThat(variant.getRequestBody().getContent()).hasSize(1); + assertThat(variant.getResponses().get("200").getContent()).hasSize(1); + } + + // GET /reports/{id}: no request body, response {json -> Report, directlog -> binary} => 2 variants. + List getVariants = contentTypeVariants(openAPI.getPaths().get("/reports/{id}").getGet()); + assertThat(getVariants).extracting(Operation::getOperationId) + .containsExactlyInAnyOrder("getReportAsJson", "getReportAsDirectlog"); + } + + @Test + public void splitOperationsByContentTypeLeavesUnambiguousOperationsUntouched() { + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setSplitOperationsByContentType(true); + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/petstore.yaml"); + + codegen.preprocessOpenAPI(openAPI); + + // petstore has no operation exposing several content-types with different schemas: nothing is divided. + boolean anyDivided = openAPI.getPaths().values().stream() + .flatMap(path -> path.readOperations().stream()) + .anyMatch(op -> op.getExtensions() != null && op.getExtensions().containsKey(DefaultCodegen.X_CONTENT_TYPE_VARIANTS)); + assertThat(anyDivided).isFalse(); + } + + @SuppressWarnings("unchecked") + private static List contentTypeVariants(Operation operation) { + return (List) operation.getExtensions().get(DefaultCodegen.X_CONTENT_TYPE_VARIANTS); + } } diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type.yaml new file mode 100644 index 000000000000..7b36bb577e41 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type.yaml @@ -0,0 +1,70 @@ +openapi: 3.0.1 +info: + title: split operations by content-type (issue 6708) + version: 1.0.0 +paths: + /reports/{id}: + get: + operationId: getReport + tags: + - report + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/directlog: + schema: + type: string + format: binary + /reports: + post: + operationId: createReport + tags: + - report + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/xml: + schema: + $ref: '#/components/schemas/ReportXml' + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + application/pdf: + schema: + type: string + format: binary +components: + schemas: + Report: + type: object + properties: + id: + type: string + name: + type: string + ReportXml: + type: object + properties: + ref: + type: string + Receipt: + type: object + properties: + number: + type: string From 460b1fb43db2143ec0f3b19c63f5b8c82bbf8527 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 13:57:51 +0200 Subject: [PATCH 02/11] #6708 : Move the clone methods to ModelUtils to lightweight DefaultCodegen --- .../openapitools/codegen/DefaultCodegen.java | 116 ++++++++---------- .../codegen/utils/ModelUtils.java | 41 +++++++ .../codegen/DefaultCodegenTest.java | 20 +++ .../3_0/issue6708-method-response-target.yaml | 57 +++++++++ 4 files changed, 171 insertions(+), 63 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-method-response-target.yaml diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 826991b97fdd..0dca3db729c1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1158,24 +1158,21 @@ private String findMultiSchemaSuccessResponseCode(OpenAPI openAPI, Operation ope if (operation.getResponses() == null) { return null; } - for (Map.Entry entry : operation.getResponses().entrySet()) { - String code = entry.getKey(); - if (code == null || code.length() != 3 || code.charAt(0) != '2') { - continue; - } - ApiResponse response = ModelUtils.getReferencedApiResponse(openAPI, entry.getValue()); - Content content = response == null ? null : response.getContent(); - if (content == null || content.size() < 2) { - continue; - } - long distinct = content.values().stream() - .map(mt -> schemaKey(mt == null ? null : mt.getSchema())) - .distinct().count(); - if (distinct >= 2) { - return code; - } + // Only split the response the generator actually derives the return type from, so the variants' + // return types and Accept headers stay consistent (see findMethodResponse). + String code = findMethodResponseCode(operation.getResponses()); + if (code == null) { + return null; } - return null; + ApiResponse response = ModelUtils.getReferencedApiResponse(openAPI, operation.getResponses().get(code)); + Content content = response == null ? null : response.getContent(); + if (content == null || content.size() < 2) { + return null; + } + long distinctSchemas = content.values().stream() + .map(mt -> schemaKey(mt == null ? null : mt.getSchema())) + .distinct().count(); + return distinctSchemas >= 2 ? code : null; } /** @@ -1184,7 +1181,12 @@ private String findMultiSchemaSuccessResponseCode(OpenAPI openAPI, Operation ope */ private Operation buildOperationVariant(OpenAPI openAPI, Operation original, String baseId, String requestMediaType, String responseMediaType, String targetResponseCode, ApiResponse targetResponse) { - Operation variant = shallowCopyOperation(original); + boolean openapi31 = specVersionGreaterThanOrEqualTo310(openAPI); + Operation variant = ModelUtils.cloneOperation(original, openapi31); + // generators (e.g. SpringCodegen) read the extensions map without null-guards + if (variant.getExtensions() == null) { + variant.setExtensions(new LinkedHashMap<>()); + } // typed, collision-free operationId: request -> "With", response -> "As" StringBuilder operationId = new StringBuilder(baseId); @@ -1198,51 +1200,26 @@ private Operation buildOperationVariant(OpenAPI openAPI, Operation original, Str if (requestMediaType != null) { RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, original.getRequestBody()); - variant.setRequestBody(narrowRequestBody(requestBody, requestMediaType)); + variant.setRequestBody(narrowRequestBody(requestBody, requestMediaType, openapi31)); } if (responseMediaType != null) { - variant.setResponses(narrowResponses(original.getResponses(), targetResponseCode, targetResponse, responseMediaType)); + variant.setResponses(narrowResponses(original.getResponses(), targetResponseCode, targetResponse, responseMediaType, openapi31)); } return variant; } - /** Shallow-copies an {@link Operation}, giving the copy its own mutable parameter/extension lists. */ - private Operation shallowCopyOperation(Operation source) { - Operation copy = new Operation(); - copy.setTags(source.getTags()); - copy.setSummary(source.getSummary()); - copy.setDescription(source.getDescription()); - copy.setExternalDocs(source.getExternalDocs()); - copy.setOperationId(source.getOperationId()); - copy.setParameters(source.getParameters() == null ? null : new ArrayList<>(source.getParameters())); - copy.setRequestBody(source.getRequestBody()); - copy.setResponses(source.getResponses()); - copy.setCallbacks(source.getCallbacks()); - copy.setDeprecated(source.getDeprecated()); - copy.setSecurity(source.getSecurity() == null ? null : new ArrayList<>(source.getSecurity())); - copy.setServers(source.getServers()); - // Keep a non-null extensions map: generators (e.g. SpringCodegen) read it without null-guards. - copy.setExtensions(source.getExtensions() == null ? new LinkedHashMap<>() : new LinkedHashMap<>(source.getExtensions())); - return copy; - } - - private RequestBody narrowRequestBody(RequestBody source, String mediaType) { - RequestBody copy = new RequestBody(); - copy.setDescription(source.getDescription()); - copy.setRequired(source.getRequired()); - copy.setExtensions(source.getExtensions()); - Content content = new Content(); - content.addMediaType(mediaType, source.getContent().get(mediaType)); - copy.setContent(content); + private RequestBody narrowRequestBody(RequestBody source, String mediaType, boolean openapi31) { + RequestBody copy = ModelUtils.cloneRequestBody(source, openapi31); + copy.setContent(singleContent(source.getContent(), mediaType)); return copy; } - private ApiResponses narrowResponses(ApiResponses responses, String targetCode, ApiResponse targetResponse, String mediaType) { + private ApiResponses narrowResponses(ApiResponses responses, String targetCode, ApiResponse targetResponse, String mediaType, boolean openapi31) { ApiResponses copy = new ApiResponses(); copy.setExtensions(responses.getExtensions()); for (Map.Entry entry : responses.entrySet()) { if (entry.getKey().equals(targetCode)) { - copy.addApiResponse(entry.getKey(), narrowApiResponse(targetResponse, mediaType)); + copy.addApiResponse(entry.getKey(), narrowApiResponse(targetResponse, mediaType, openapi31)); } else { copy.addApiResponse(entry.getKey(), entry.getValue()); } @@ -1250,18 +1227,19 @@ private ApiResponses narrowResponses(ApiResponses responses, String targetCode, return copy; } - private ApiResponse narrowApiResponse(ApiResponse source, String mediaType) { - ApiResponse copy = new ApiResponse(); - copy.setDescription(source.getDescription()); - copy.setHeaders(source.getHeaders()); - copy.setLinks(source.getLinks()); - copy.setExtensions(source.getExtensions()); - Content content = new Content(); - content.addMediaType(mediaType, source.getContent().get(mediaType)); - copy.setContent(content); + private ApiResponse narrowApiResponse(ApiResponse source, String mediaType, boolean openapi31) { + ApiResponse copy = ModelUtils.cloneApiResponse(source, openapi31); + copy.setContent(singleContent(source.getContent(), mediaType)); return copy; } + /** A new {@link Content} holding only {@code mediaType} taken from {@code source}. */ + private static Content singleContent(Content source, String mediaType) { + Content content = new Content(); + content.addMediaType(mediaType, source.get(mediaType)); + return content; + } + /** Stable identity key for a schema: its {@code $ref} when present, else a structural key. */ private static String schemaKey(Schema schema) { if (schema == null) { @@ -4824,6 +4802,21 @@ protected void setNonArrayMapProperty(CodegenProperty property, String type) { * @return default method response or null if not found */ protected ApiResponse findMethodResponse(ApiResponses responses) { + String code = findMethodResponseCode(responses); + if (code == null) { + return null; + } + return ModelUtils.getReferencedApiResponse(openAPI, responses.get(code)); + } + + /** + * Returns the response code the operation's return type is derived from: the lowest 2xx code, or + * {@code "default"} when no 2xx is present. + * + * @param responses the API responses of an operation + * @return the selected response code, or {@code null} if there is no success/default response + */ + protected String findMethodResponseCode(ApiResponses responses) { String code = null; for (String responseCode : responses.keySet()) { if (responseCode.startsWith("2") || responseCode.equals("default")) { @@ -4832,10 +4825,7 @@ protected ApiResponse findMethodResponse(ApiResponses responses) { } } } - if (code == null) { - return null; - } - return ModelUtils.getReferencedApiResponse(openAPI, responses.get(code)); + return code; } /** diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 88346d9046f7..41fe5ed14ade 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.AnnotationsUtils; +import io.swagger.v3.core.util.Json; +import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -2315,6 +2317,45 @@ public static Schema cloneSchema(Schema schema, boolean openapi31) { } } + /** + * Deep-clones an {@link Operation} through the swagger object mapper (like {@link #cloneSchema}). + * + * @param source the operation to clone + * @param openapi31 whether the document is OpenAPI 3.1 (selects the matching mapper so embedded + * schemas are serialized with the right dialect) + * @return a deep clone of {@code source} + */ + public static Operation cloneOperation(Operation source, boolean openapi31) { + return cloneViaMapper(source, Operation.class, openapi31); + } + + /** + * Deep-clones a {@link RequestBody} through the swagger object mapper. + * + * @param source the request body to clone + * @param openapi31 whether the document is OpenAPI 3.1 + * @return a deep clone of {@code source} + */ + public static RequestBody cloneRequestBody(RequestBody source, boolean openapi31) { + return cloneViaMapper(source, RequestBody.class, openapi31); + } + + /** + * Deep-clones an {@link ApiResponse} through the swagger object mapper. + * + * @param source the response to clone + * @param openapi31 whether the document is OpenAPI 3.1 + * @return a deep clone of {@code source} + */ + public static ApiResponse cloneApiResponse(ApiResponse source, boolean openapi31) { + return cloneViaMapper(source, ApiResponse.class, openapi31); + } + + private static T cloneViaMapper(T source, Class type, boolean openapi31) { + ObjectMapper mapper = openapi31 ? Json31.mapper() : Json.mapper(); + return mapper.convertValue(source, type); + } + /** * Simplifies the schema by removing the oneOfAnyOf if the oneOfAnyOf only contains a single non-null sub-schema * diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index c3d30fe441cd..9cfdc868a0dd 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -5265,6 +5265,26 @@ public void splitOperationsByContentTypeLeavesUnambiguousOperationsUntouched() { assertThat(anyDivided).isFalse(); } + @Test + public void splitOperationsByContentTypeUsesTheMethodResponse() { + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setSplitOperationsByContentType(true); + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/issue6708-method-response-target.yaml"); + + codegen.preprocessOpenAPI(openAPI); + + // /a: the method response (200, the lowest 2xx) is multi-content -> split by content-type. + assertThat(contentTypeVariants(openAPI.getPaths().get("/a").getGet())) + .extracting(Operation::getOperationId) + .containsExactlyInAnyOrder("getAAsJson", "getAAsPdf"); + + // /b: only the non-method response (206) is multi-content; the method response (200) is single, + // so the operation is left untouched - the generator derives the return type from 200 only. + Operation getB = openAPI.getPaths().get("/b").getGet(); + assertThat(getB.getExtensions() != null + && getB.getExtensions().containsKey(DefaultCodegen.X_CONTENT_TYPE_VARIANTS)).isFalse(); + } + @SuppressWarnings("unchecked") private static List contentTypeVariants(Operation operation) { return (List) operation.getExtensions().get(DefaultCodegen.X_CONTENT_TYPE_VARIANTS); diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-method-response-target.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-method-response-target.yaml new file mode 100644 index 000000000000..1e512873e41d --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-method-response-target.yaml @@ -0,0 +1,57 @@ +openapi: 3.0.1 +info: + title: split targets the method response (issue 6708) + version: 1.0.0 +paths: + /a: + get: + operationId: getA + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/A' + application/pdf: + schema: + type: string + format: binary + '206': + description: partial + content: + application/json: + schema: + $ref: '#/components/schemas/A' + /b: + get: + operationId: getB + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/A' + '206': + description: partial + content: + application/json: + schema: + $ref: '#/components/schemas/B' + application/pdf: + schema: + type: string + format: binary +components: + schemas: + A: + type: object + properties: + id: + type: string + B: + type: object + properties: + ref: + type: string From abee4a4a8f3aca1b9a4734b070d4752ae681b568 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 14:52:36 +0200 Subject: [PATCH 03/11] #6708 : Add new split operations option in every providers --- .../org/openapitools/codegen/CodegenConstants.java | 3 +++ .../org/openapitools/codegen/DefaultCodegen.java | 12 ++++-------- .../codegen/options/BashClientOptionsProvider.java | 1 + .../codegen/options/DartClientOptionsProvider.java | 1 + .../options/DartDioClientOptionsProvider.java | 1 + .../codegen/options/ElixirClientOptionsProvider.java | 1 + .../options/HaskellServantOptionsProvider.java | 1 + .../options/HaskellYesodServerOptionsProvider.java | 1 + .../codegen/options/PhpClientOptionsProvider.java | 1 + .../options/PhpLumenServerOptionsProvider.java | 1 + .../options/PhpSlim4ServerOptionsProvider.java | 1 + .../codegen/options/RubyClientOptionsProvider.java | 1 + .../options/ScalaAkkaClientOptionsProvider.java | 1 + .../codegen/options/Swift5OptionsProvider.java | 1 + .../options/Swift6ClientCodegenOptionsProvider.java | 1 + .../TypeScriptSharedClientOptionsProvider.java | 1 + .../codegen/options/XojoClientOptionsProvider.java | 1 + 17 files changed, 22 insertions(+), 8 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index 5d038971f748..bdc494e5a10b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -150,6 +150,9 @@ public class CodegenConstants { public static final String PREPEND_FORM_OR_BODY_PARAMETERS = "prependFormOrBodyParameters"; public static final String PREPEND_FORM_OR_BODY_PARAMETERS_DESC = "Add form or body parameters to the beginning of the parameter list."; + public static final String SPLIT_OPERATIONS_BY_CONTENT_TYPE = "splitOperationsByContentType"; + public static final String SPLIT_OPERATIONS_BY_CONTENT_TYPE_DESC = "Generate one operation per request/response content-type when an operation exposes several content-types with different schemas."; + public static final String USE_DATETIME_OFFSET = "useDateTimeOffset"; public static final String USE_DATETIME_OFFSET_DESC = "Use DateTimeOffset to model date-time properties"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 0dca3db729c1..48ff821b614e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -419,7 +419,7 @@ public void processOpts() { convertPropertyToBooleanAndWriteBack(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, this::setPrependFormOrBodyParameters); convertPropertyToBooleanAndWriteBack(CodegenConstants.ENSURE_UNIQUE_PARAMS, this::setEnsureUniqueParams); convertPropertyToBooleanAndWriteBack(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, this::setAllowUnicodeIdentifiers); - convertPropertyToBooleanAndWriteBack(SPLIT_OPERATIONS_BY_CONTENT_TYPE, this::setSplitOperationsByContentType); + convertPropertyToBooleanAndWriteBack(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, this::setSplitOperationsByContentType); convertPropertyToStringAndWriteBack(CodegenConstants.API_NAME_PREFIX, this::setApiNamePrefix); convertPropertyToStringAndWriteBack(CodegenConstants.API_NAME_SUFFIX, this::setApiNameSuffix); convertPropertyToStringAndWriteBack(CodegenConstants.MODEL_NAME_PREFIX, this::setModelNamePrefix); @@ -1058,9 +1058,6 @@ public void postProcessResponseWithProperty(CodegenResponse response, CodegenPro public void postProcessParameter(CodegenParameter parameter) { } - /** Opt-in option key: split operations that expose several request/response content-types. */ - public static final String SPLIT_OPERATIONS_BY_CONTENT_TYPE = "splitOperationsByContentType"; - /** Internal vendor extension carrying the {@code List} a divided operation expands to. */ public static final String X_CONTENT_TYPE_VARIANTS = "x-content-type-variants"; @@ -1071,7 +1068,7 @@ public void setSplitOperationsByContentType(boolean splitOperationsByContentType } /** - * When {@link #SPLIT_OPERATIONS_BY_CONTENT_TYPE} is enabled, divides every operation whose request + * When {@link CodegenConstants#SPLIT_OPERATIONS_BY_CONTENT_TYPE} is enabled, divides every operation whose request * body and/or success response expose several content-types with different schemas into one * operation per content-type (the cartesian product of the request and response axes). The variants * are stored on the original {@link Operation} under {@link #X_CONTENT_TYPE_VARIANTS} and expanded by @@ -2040,9 +2037,8 @@ public DefaultCodegen() { cliOptions.add(CliOption.newBoolean(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS_DESC).defaultValue(Boolean.FALSE.toString())); // option to split operations that expose several request/response content-types with different schemas - cliOptions.add(CliOption.newBoolean(SPLIT_OPERATIONS_BY_CONTENT_TYPE, - "Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.") - .defaultValue(Boolean.FALSE.toString())); + cliOptions.add(CliOption.newBoolean(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, + CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE_DESC).defaultValue(Boolean.FALSE.toString())); // option to change how we process + set the data in the discriminator mapping CliOption legacyDiscriminatorBehaviorOpt = CliOption.newBoolean(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR_DESC).defaultValue(Boolean.TRUE.toString()); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java index 76b523fcd728..95a43280b62b 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java @@ -67,6 +67,7 @@ public Map createOptions() { .put(BashClientCodegen.APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME, APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "false") + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, "false") .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "false") .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java index e8ae5313da8b..4e344a9c69d7 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java @@ -53,6 +53,7 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(DartClientCodegen.PUB_LIBRARY, PUB_LIBRARY_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java index a8e0f8381df0..a26b64363334 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java @@ -52,6 +52,7 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(DartDioClientCodegen.PUB_LIBRARY, PUB_LIBRARY_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java index 32b7b3d34151..691805e2f913 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java @@ -37,6 +37,7 @@ public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "false") + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, "false") .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "false") .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, "false") diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java index b6cb61abc193..80ef8ae9a544 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java @@ -44,6 +44,7 @@ public Map createOptions() { return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java index 66fd08f19aaa..04b9b39dae30 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java @@ -25,6 +25,7 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java index bf26ac750fa7..89368c3f91ed 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java @@ -55,6 +55,7 @@ public Map createOptions() { return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(PhpClientCodegen.VARIABLE_NAMING_CONVENTION, VARIABLE_NAMING_CONVENTION_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java index ee795a038735..c76041e23b84 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java @@ -57,6 +57,7 @@ public Map createOptions() { .put(AbstractPhpCodegen.SRC_BASE_PATH, SRC_BASE_PATH_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java index 7ebaece2aae3..cd261da45a67 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java @@ -61,6 +61,7 @@ public Map createOptions() { .put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE) .put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java index 4578b058af70..0c069c6f316a 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java @@ -64,6 +64,7 @@ public Map createOptions() { .put(RubyClientCodegen.GEM_AUTHOR_EMAIL, GEM_AUTHOR_EMAIL_VALUE) .put(RubyClientCodegen.GEM_METADATA, GEM_METADATA_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true") diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java index 7c4e5d4a1b92..94f10a5daf0a 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java @@ -48,6 +48,7 @@ public Map createOptions() { return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java index 3485cc879032..3fcab35754a7 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java @@ -68,6 +68,7 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(Swift5ClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java index e470c5646c00..4da0f6b43cf8 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java @@ -70,6 +70,7 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(Swift6ClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java index be020be5a7bb..14df72eae70e 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java @@ -49,6 +49,7 @@ default Map createOptions() { entry(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE, ENUM_UNKNOWN_DEFAULT_CASE_VALUE), entry(AbstractTypeScriptClientCodegen.ENUM_PROPERTY_NAMING_REPLACE_SPECIAL_CHAR, ENUM_PROPERTY_NAMING_REPLACE_SPECIAL_CHAR_VALUE), entry(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE), + entry(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false"), entry(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE), entry(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE), entry(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, LEGACY_DISCRIMINATOR_BEHAVIOUR_VALUE), diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java index a7f9a8697658..b2beb3ef243d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java @@ -54,6 +54,7 @@ public Map createOptions() { .put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, "true") .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "true") + .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "true") .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, "false") .put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "false") From 927f47691ce6ca66c7a3f74e8630b1436d4de6f9 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 15:02:40 +0200 Subject: [PATCH 04/11] #6708 : Build project and update samples --- docs/generators/ada-server.md | 1 + docs/generators/ada.md | 1 + docs/generators/android.md | 1 + docs/generators/apache2.md | 1 + docs/generators/apex.md | 1 + docs/generators/asciidoc.md | 1 + docs/generators/aspnet-fastendpoints.md | 1 + docs/generators/avro-schema.md | 1 + docs/generators/bash.md | 1 + docs/generators/c.md | 1 + docs/generators/clojure.md | 1 + docs/generators/cpp-httplib-server.md | 1 + docs/generators/cpp-qt-client.md | 1 + docs/generators/cpp-qt-qhttpengine-server.md | 1 + docs/generators/cpp-tiny.md | 1 + docs/generators/cpp-tizen.md | 1 + docs/generators/cpp-ue4.md | 1 + docs/generators/crystal.md | 1 + docs/generators/cwiki.md | 1 + docs/generators/dart-dio.md | 1 + docs/generators/dart.md | 1 + docs/generators/dynamic-html.md | 1 + docs/generators/elixir.md | 1 + docs/generators/fsharp-functions.md | 1 + docs/generators/gdscript.md | 1 + docs/generators/groovy.md | 1 + docs/generators/haskell-http-client.md | 1 + docs/generators/haskell-yesod.md | 1 + docs/generators/haskell.md | 1 + docs/generators/html.md | 1 + docs/generators/html2.md | 1 + docs/generators/java-camel.md | 1 + docs/generators/java-dubbo.md | 1 + docs/generators/java-helidon-client.md | 1 + docs/generators/java-helidon-server.md | 1 + docs/generators/java-inflector.md | 1 + docs/generators/java-micronaut-client.md | 1 + docs/generators/java-micronaut-server.md | 1 + docs/generators/java-microprofile.md | 1 + docs/generators/java-msf4j.md | 1 + docs/generators/java-pkmst.md | 1 + docs/generators/java-play-framework.md | 1 + docs/generators/java-undertow-server.md | 1 + docs/generators/java-vertx-web.md | 1 + docs/generators/java-vertx.md | 1 + docs/generators/java-wiremock.md | 1 + docs/generators/java.md | 1 + docs/generators/javascript-apollo-deprecated.md | 1 + docs/generators/javascript-closure-angular.md | 1 + docs/generators/javascript-flowtyped.md | 1 + docs/generators/javascript.md | 1 + docs/generators/jaxrs-cxf-cdi.md | 1 + docs/generators/jaxrs-cxf-client.md | 1 + docs/generators/jaxrs-cxf-extended.md | 1 + docs/generators/jaxrs-cxf.md | 1 + docs/generators/jaxrs-jersey.md | 1 + docs/generators/jaxrs-resteasy-eap.md | 1 + docs/generators/jaxrs-resteasy.md | 1 + docs/generators/jaxrs-spec.md | 1 + docs/generators/jmeter.md | 1 + docs/generators/k6.md | 1 + docs/generators/markdown.md | 1 + docs/generators/nim.md | 1 + docs/generators/nodejs-express-server.md | 1 + docs/generators/ocaml.md | 1 + docs/generators/openapi-yaml.md | 1 + docs/generators/openapi.md | 1 + docs/generators/php-dt.md | 1 + docs/generators/php-flight.md | 1 + docs/generators/php-laravel.md | 1 + docs/generators/php-lumen.md | 1 + docs/generators/php-mezzio-ph.md | 1 + docs/generators/php-nextgen.md | 1 + docs/generators/php-slim4.md | 1 + docs/generators/php-symfony.md | 1 + docs/generators/php.md | 1 + docs/generators/plantuml.md | 1 + docs/generators/python-aiohttp.md | 1 + docs/generators/python-blueplanet.md | 1 + docs/generators/python-fastapi.md | 1 + docs/generators/python-flask.md | 1 + docs/generators/ruby.md | 1 + docs/generators/scala-akka-http-server.md | 1 + docs/generators/scala-akka.md | 1 + docs/generators/scala-cask.md | 1 + docs/generators/scala-gatling.md | 1 + docs/generators/scala-http4s-server.md | 1 + docs/generators/scala-http4s.md | 1 + docs/generators/scala-lagom-server-deprecated.md | 1 + docs/generators/scala-pekko.md | 1 + docs/generators/scala-play-server.md | 1 + docs/generators/scala-sttp.md | 1 + docs/generators/scala-sttp4-jsoniter.md | 1 + docs/generators/scala-sttp4.md | 1 + docs/generators/scalatra.md | 1 + docs/generators/scalaz.md | 1 + docs/generators/spring.md | 1 + docs/generators/swift-combine.md | 1 + docs/generators/swift5.md | 1 + docs/generators/swift6.md | 1 + docs/generators/typescript-angular.md | 1 + docs/generators/typescript-aurelia.md | 1 + docs/generators/typescript-axios.md | 1 + docs/generators/typescript-fetch.md | 1 + docs/generators/typescript-inversify.md | 1 + docs/generators/typescript-jquery.md | 1 + docs/generators/typescript-nestjs-server.md | 1 + docs/generators/typescript-nestjs.md | 1 + docs/generators/typescript-node.md | 1 + docs/generators/typescript-redux-query.md | 1 + docs/generators/typescript-rxjs.md | 1 + docs/generators/typescript.md | 1 + docs/generators/wsdl-schema.md | 1 + docs/generators/xojo-client.md | 1 + docs/generators/zapier.md | 1 + 115 files changed, 115 insertions(+) diff --git a/docs/generators/ada-server.md b/docs/generators/ada-server.md index ef255ad0a889..e7cd55677774 100644 --- a/docs/generators/ada-server.md +++ b/docs/generators/ada-server.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|GNAT project name| |defaultProject| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/ada.md b/docs/generators/ada.md index dbe8100ed6b4..e3e7fb9d6dd0 100644 --- a/docs/generators/ada.md +++ b/docs/generators/ada.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|GNAT project name| |defaultProject| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/android.md b/docs/generators/android.md index eae5d263ac86..decb52bfbecd 100644 --- a/docs/generators/android.md +++ b/docs/generators/android.md @@ -38,6 +38,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useAndroidMavenGradlePlugin|A flag to toggle android-maven gradle plugin.| |true| ## IMPORT MAPPING diff --git a/docs/generators/apache2.md b/docs/generators/apache2.md index db059f001c21..a98b5f92fa82 100644 --- a/docs/generators/apache2.md +++ b/docs/generators/apache2.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |userInfoPath|Path to the user and group files| |null| ## IMPORT MAPPING diff --git a/docs/generators/apex.md b/docs/generators/apex.md index ef0cde0019f2..df64fe7c706d 100644 --- a/docs/generators/apex.md +++ b/docs/generators/apex.md @@ -30,6 +30,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/asciidoc.md b/docs/generators/asciidoc.md index 4fa26626bee2..63901722bb80 100644 --- a/docs/generators/asciidoc.md +++ b/docs/generators/asciidoc.md @@ -40,6 +40,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |specDir|path with includable markup spec files (e.g. handwritten additional docs, default: ..)| |..| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useIntroduction|use introduction section, rather than an initial abstract (default: false)| |false| |useMethodAndPath|Use HTTP method and path as operation heading, instead of operation id (default: false)| |false| |useTableTitles|Use titles for tables, rather than wrapping tables instead their own section (default: false)| |false| diff --git a/docs/generators/aspnet-fastendpoints.md b/docs/generators/aspnet-fastendpoints.md index b272b42a7e3b..53998a025061 100644 --- a/docs/generators/aspnet-fastendpoints.md +++ b/docs/generators/aspnet-fastendpoints.md @@ -30,6 +30,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |solutionGuid|The solution GUID to be used in the solution file (auto generated if not provided)| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useApiVersioning|Enable API versioning (https://fast-endpoints.com/docs/api-versioning).| |false| |useAuthentication|Enable authentication (https://fast-endpoints.com/docs/security).| |false| |useProblemDetails|Enable RFC compatible error responses (https://fast-endpoints.com/docs/configuration-settings#rfc7807-rfc9457-compatible-problem-details).| |false| diff --git a/docs/generators/avro-schema.md b/docs/generators/avro-schema.md index f409b796e8d3..60b8c9530d37 100644 --- a/docs/generators/avro-schema.md +++ b/docs/generators/avro-schema.md @@ -28,6 +28,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useLogicalTypes|Use logical types for fields, when matching OpenAPI types. Currently supported: `date-time`, `date`.| |false| ## IMPORT MAPPING diff --git a/docs/generators/bash.md b/docs/generators/bash.md index e5d12261d54f..7f69d1c804d9 100644 --- a/docs/generators/bash.md +++ b/docs/generators/bash.md @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |scriptName|The name of the script that will be generated (e.g. petstore-cli)| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/c.md b/docs/generators/c.md index f53d973c2731..06f98a2f5a51 100644 --- a/docs/generators/c.md +++ b/docs/generators/c.md @@ -28,6 +28,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useJsonUnformatted|Use cJSON_PrintUnformatted instead of cJSON_Print when creating the JSON string.| |false| ## IMPORT MAPPING diff --git a/docs/generators/clojure.md b/docs/generators/clojure.md index d152d949d75b..a6ec821f805f 100644 --- a/docs/generators/clojure.md +++ b/docs/generators/clojure.md @@ -33,6 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectVersion|version of the project (Default: using info.version or "1.0.0")| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/cpp-httplib-server.md b/docs/generators/cpp-httplib-server.md index 8cdbe5e96c72..2fe50b6920fd 100644 --- a/docs/generators/cpp-httplib-server.md +++ b/docs/generators/cpp-httplib-server.md @@ -28,6 +28,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-qt-client.md b/docs/generators/cpp-qt-client.md index 7ca05b6930a9..8190b26f5091 100644 --- a/docs/generators/cpp-qt-client.md +++ b/docs/generators/cpp-qt-client.md @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-qt-qhttpengine-server.md b/docs/generators/cpp-qt-qhttpengine-server.md index 9fbf3fca8020..b353ad978949 100644 --- a/docs/generators/cpp-qt-qhttpengine-server.md +++ b/docs/generators/cpp-qt-qhttpengine-server.md @@ -30,6 +30,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-tiny.md b/docs/generators/cpp-tiny.md index 97e0e7eea4f3..aba436b1f2ee 100644 --- a/docs/generators/cpp-tiny.md +++ b/docs/generators/cpp-tiny.md @@ -28,6 +28,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-tizen.md b/docs/generators/cpp-tizen.md index 58f0390bd8b8..fa8a96821286 100644 --- a/docs/generators/cpp-tizen.md +++ b/docs/generators/cpp-tizen.md @@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-ue4.md b/docs/generators/cpp-ue4.md index b8c44498f35e..f512560586e0 100644 --- a/docs/generators/cpp-ue4.md +++ b/docs/generators/cpp-ue4.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |unrealModuleName|Name of the generated unreal module (optional)| |OpenAPI| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| diff --git a/docs/generators/crystal.md b/docs/generators/crystal.md index cf41d7e11ab0..56b388bee8f3 100644 --- a/docs/generators/crystal.md +++ b/docs/generators/crystal.md @@ -36,6 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |shardVersion|shard version.| |1.0.0| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/cwiki.md b/docs/generators/cwiki.md index 058e50555b43..94bc417a0813 100644 --- a/docs/generators/cwiki.md +++ b/docs/generators/cwiki.md @@ -35,6 +35,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/dart-dio.md b/docs/generators/dart-dio.md index 21a5a07357c7..9ef64a28c536 100644 --- a/docs/generators/dart-dio.md +++ b/docs/generators/dart-dio.md @@ -42,6 +42,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useEnumExtension|Allow the 'x-enum-values' extension for enums| |false| |useOptional|Use Optional<T> to distinguish absent, null, and present for optional fields (Dart 3+)| |false| diff --git a/docs/generators/dart.md b/docs/generators/dart.md index a06c695af0cf..6e0fd3bbd625 100644 --- a/docs/generators/dart.md +++ b/docs/generators/dart.md @@ -38,6 +38,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useEnumExtension|Allow the 'x-enum-values' extension for enums| |false| |useOptional|Use Optional<T> to distinguish absent, null, and present for optional fields (Dart 3+)| |false| diff --git a/docs/generators/dynamic-html.md b/docs/generators/dynamic-html.md index 569cd7154ced..3f4685332148 100644 --- a/docs/generators/dynamic-html.md +++ b/docs/generators/dynamic-html.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/elixir.md b/docs/generators/elixir.md index f235da179c5a..40cff3895277 100644 --- a/docs/generators/elixir.md +++ b/docs/generators/elixir.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/fsharp-functions.md b/docs/generators/fsharp-functions.md index 4e589d22802e..fc4712845e25 100644 --- a/docs/generators/fsharp-functions.md +++ b/docs/generators/fsharp-functions.md @@ -35,6 +35,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |OpenAPI/src| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/gdscript.md b/docs/generators/gdscript.md index ee3abee25371..f9fe5a99d743 100644 --- a/docs/generators/gdscript.md +++ b/docs/generators/gdscript.md @@ -30,6 +30,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/groovy.md b/docs/generators/groovy.md index a7125c0350b4..c1a109e5eabb 100644 --- a/docs/generators/groovy.md +++ b/docs/generators/groovy.md @@ -67,6 +67,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/groovy| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/haskell-http-client.md b/docs/generators/haskell-http-client.md index 4a06d06b7373..fea5718ab076 100644 --- a/docs/generators/haskell-http-client.md +++ b/docs/generators/haskell-http-client.md @@ -46,6 +46,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |requestType|Set the name of the type used to generate requests| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |strictFields|Add strictness annotations to all model fields| |true| |useKatip|Sets the default value for the UseKatip cabal flag. If true, the katip package provides logging instead of monad-logger| |true| diff --git a/docs/generators/haskell-yesod.md b/docs/generators/haskell-yesod.md index 3d60cf095d8f..21a382cb630f 100644 --- a/docs/generators/haskell-yesod.md +++ b/docs/generators/haskell-yesod.md @@ -28,6 +28,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|name of the project (Default: generated from info.title or "openapi-haskell-yesod-server")| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/haskell.md b/docs/generators/haskell.md index 192d9b58ee56..7edb032a956c 100644 --- a/docs/generators/haskell.md +++ b/docs/generators/haskell.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serveStatic|serve will serve files from the directory 'static'.| |true| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useCustomMonad|use a custom monad instead of the default Handler| |false| ## IMPORT MAPPING diff --git a/docs/generators/html.md b/docs/generators/html.md index aa91c8e8daf2..7a7bb941fd76 100644 --- a/docs/generators/html.md +++ b/docs/generators/html.md @@ -35,6 +35,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/html2.md b/docs/generators/html2.md index 91d5b9e51d3b..26d4edc7f09f 100644 --- a/docs/generators/html2.md +++ b/docs/generators/html2.md @@ -39,6 +39,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |pythonPackageName|package name for generated python code| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md index b67c8e111a69..5e68a5b62eb9 100644 --- a/docs/generators/java-camel.md +++ b/docs/generators/java-camel.md @@ -104,6 +104,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| |substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| diff --git a/docs/generators/java-dubbo.md b/docs/generators/java-dubbo.md index d39495d8a2e0..193557fd7d32 100644 --- a/docs/generators/java-dubbo.md +++ b/docs/generators/java-dubbo.md @@ -77,6 +77,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|API title name| |null| |useGenericResponse|Use generic response wrapper| |false| diff --git a/docs/generators/java-helidon-client.md b/docs/generators/java-helidon-client.md index cab0e57ada6f..7d5b13102c82 100644 --- a/docs/generators/java-helidon-client.md +++ b/docs/generators/java-helidon-client.md @@ -64,6 +64,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-helidon-server.md b/docs/generators/java-helidon-server.md index e817d1e1e2b3..6870f3277754 100644 --- a/docs/generators/java-helidon-server.md +++ b/docs/generators/java-helidon-server.md @@ -65,6 +65,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useAbstractClass|Whether to generate abstract classes for REST API instead of interfaces.| |false| |useBeanValidation|Use Bean Validation| |false| diff --git a/docs/generators/java-inflector.md b/docs/generators/java-inflector.md index 3cc8851281ed..29c14fa22f45 100644 --- a/docs/generators/java-inflector.md +++ b/docs/generators/java-inflector.md @@ -69,6 +69,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-micronaut-client.md b/docs/generators/java-micronaut-client.md index 5b0fcc3ab460..5a7972e4cb6e 100644 --- a/docs/generators/java-micronaut-client.md +++ b/docs/generators/java-micronaut-client.md @@ -84,6 +84,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |test|Specify which test tool to generate files for|
**junit**
Use JUnit as test tool
**spock**
Use Spock as test tool
|junit| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|Client service name| |null| diff --git a/docs/generators/java-micronaut-server.md b/docs/generators/java-micronaut-server.md index eb6e68a82e57..c7b3d31eb7f0 100644 --- a/docs/generators/java-micronaut-server.md +++ b/docs/generators/java-micronaut-server.md @@ -82,6 +82,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |test|Specify which test tool to generate files for|
**junit**
Use JUnit as test tool
**spock**
Use Spock as test tool
|junit| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|Client service name| |null| diff --git a/docs/generators/java-microprofile.md b/docs/generators/java-microprofile.md index f6a93340b5b0..6070f42306a6 100644 --- a/docs/generators/java-microprofile.md +++ b/docs/generators/java-microprofile.md @@ -89,6 +89,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportStreaming|Support streaming endpoint (beta)| |false| |supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false| |supportVertxFuture|Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.| |false| diff --git a/docs/generators/java-msf4j.md b/docs/generators/java-msf4j.md index b806ca5901a3..337a176b9ce3 100644 --- a/docs/generators/java-msf4j.md +++ b/docs/generators/java-msf4j.md @@ -72,6 +72,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/java-pkmst.md b/docs/generators/java-pkmst.md index dbc4a66daef9..37a45edca5cc 100644 --- a/docs/generators/java-pkmst.md +++ b/docs/generators/java-pkmst.md @@ -73,6 +73,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |springBootAdminUri|Spring-Boot URI| |null| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |null| diff --git a/docs/generators/java-play-framework.md b/docs/generators/java-play-framework.md index 0eb293d1f84b..1d9611442989 100644 --- a/docs/generators/java-play-framework.md +++ b/docs/generators/java-play-framework.md @@ -73,6 +73,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |/app| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|Support Async operations| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |openapi-java-playframework| diff --git a/docs/generators/java-undertow-server.md b/docs/generators/java-undertow-server.md index 3e41d2e24485..066ad13f6dfc 100644 --- a/docs/generators/java-undertow-server.md +++ b/docs/generators/java-undertow-server.md @@ -69,6 +69,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-vertx-web.md b/docs/generators/java-vertx-web.md index 2530cd52bdf9..d4587546d9cf 100644 --- a/docs/generators/java-vertx-web.md +++ b/docs/generators/java-vertx-web.md @@ -69,6 +69,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-vertx.md b/docs/generators/java-vertx.md index cb91eeb2c753..1ad574964e95 100644 --- a/docs/generators/java-vertx.md +++ b/docs/generators/java-vertx.md @@ -71,6 +71,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-wiremock.md b/docs/generators/java-wiremock.md index c9ae878a03f5..652a1532a64c 100644 --- a/docs/generators/java-wiremock.md +++ b/docs/generators/java-wiremock.md @@ -69,6 +69,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java.md b/docs/generators/java.md index 780b1aca9bf6..ca2cc730606e 100644 --- a/docs/generators/java.md +++ b/docs/generators/java.md @@ -89,6 +89,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportStreaming|Support streaming endpoint (beta)| |false| |supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false| |supportVertxFuture|Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.| |false| diff --git a/docs/generators/javascript-apollo-deprecated.md b/docs/generators/javascript-apollo-deprecated.md index d416fc0afd83..5f9f9e858e17 100644 --- a/docs/generators/javascript-apollo-deprecated.md +++ b/docs/generators/javascript-apollo-deprecated.md @@ -40,6 +40,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useInheritance|use JavaScript prototype chains & delegation for inheritance| |true| |usePromises|use Promises as return values from the client API, instead of superagent callbacks| |false| diff --git a/docs/generators/javascript-closure-angular.md b/docs/generators/javascript-closure-angular.md index fb69b29ef077..24fc66c37f16 100644 --- a/docs/generators/javascript-closure-angular.md +++ b/docs/generators/javascript-closure-angular.md @@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useEs6|use ES6 templates| |false| ## IMPORT MAPPING diff --git a/docs/generators/javascript-flowtyped.md b/docs/generators/javascript-flowtyped.md index 9c194758ece0..84f9c23856fa 100644 --- a/docs/generators/javascript-flowtyped.md +++ b/docs/generators/javascript-flowtyped.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/javascript.md b/docs/generators/javascript.md index 38e933d7ae5f..8755b0581bd8 100644 --- a/docs/generators/javascript.md +++ b/docs/generators/javascript.md @@ -42,6 +42,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useInheritance|use JavaScript prototype chains & delegation for inheritance| |true| |usePromises|use Promises as return values from the client API, instead of superagent callbacks| |false| |useURLSearchParams|use JS build-in UrlSearchParams, instead of deprecated npm lib 'querystring'| |true| diff --git a/docs/generators/jaxrs-cxf-cdi.md b/docs/generators/jaxrs-cxf-cdi.md index 54e88fd00a53..4835693419ff 100644 --- a/docs/generators/jaxrs-cxf-cdi.md +++ b/docs/generators/jaxrs-cxf-cdi.md @@ -77,6 +77,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|Wrap responses in CompletionStage type, allowing asynchronous computation (requires JAX-RS 2.1).| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| diff --git a/docs/generators/jaxrs-cxf-client.md b/docs/generators/jaxrs-cxf-client.md index a3835496fda8..54ca87d4bb03 100644 --- a/docs/generators/jaxrs-cxf-client.md +++ b/docs/generators/jaxrs-cxf-client.md @@ -71,6 +71,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk.| |false| |useBeanValidation|Use BeanValidation API annotations| |false| diff --git a/docs/generators/jaxrs-cxf-extended.md b/docs/generators/jaxrs-cxf-extended.md index e8575723b309..a1c60490c0a4 100644 --- a/docs/generators/jaxrs-cxf-extended.md +++ b/docs/generators/jaxrs-cxf-extended.md @@ -80,6 +80,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportMultipleSpringServices|Support generation of Spring services from multiple specifications| |false| |testDataControlFile|JSON file to control test data generation| |null| |testDataFile|JSON file to contain generated test data| |null| diff --git a/docs/generators/jaxrs-cxf.md b/docs/generators/jaxrs-cxf.md index c54b42ab061c..a450961e3907 100644 --- a/docs/generators/jaxrs-cxf.md +++ b/docs/generators/jaxrs-cxf.md @@ -78,6 +78,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk.| |false| diff --git a/docs/generators/jaxrs-jersey.md b/docs/generators/jaxrs-jersey.md index b464219f0e82..ab46d09a13cd 100644 --- a/docs/generators/jaxrs-jersey.md +++ b/docs/generators/jaxrs-jersey.md @@ -72,6 +72,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-resteasy-eap.md b/docs/generators/jaxrs-resteasy-eap.md index 4bbee723e5a9..41a6403bf3cf 100644 --- a/docs/generators/jaxrs-resteasy-eap.md +++ b/docs/generators/jaxrs-resteasy-eap.md @@ -72,6 +72,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-resteasy.md b/docs/generators/jaxrs-resteasy.md index d61e43bedc21..ded91017f160 100644 --- a/docs/generators/jaxrs-resteasy.md +++ b/docs/generators/jaxrs-resteasy.md @@ -72,6 +72,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-spec.md b/docs/generators/jaxrs-spec.md index b5225bffd43e..1c15105fb212 100644 --- a/docs/generators/jaxrs-spec.md +++ b/docs/generators/jaxrs-spec.md @@ -78,6 +78,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|Wrap responses in CompletionStage type, allowing asynchronous computation (requires JAX-RS 2.1).| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| diff --git a/docs/generators/jmeter.md b/docs/generators/jmeter.md index 7e65ce851381..b8b108320715 100644 --- a/docs/generators/jmeter.md +++ b/docs/generators/jmeter.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/k6.md b/docs/generators/k6.md index 6c57d05e5ccc..744b24eedb41 100644 --- a/docs/generators/k6.md +++ b/docs/generators/k6.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/markdown.md b/docs/generators/markdown.md index e4402aff390f..d8fa5dbdd9bd 100644 --- a/docs/generators/markdown.md +++ b/docs/generators/markdown.md @@ -25,6 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/nim.md b/docs/generators/nim.md index 2c7cbaf98c8b..174744de8f34 100644 --- a/docs/generators/nim.md +++ b/docs/generators/nim.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/nodejs-express-server.md b/docs/generators/nodejs-express-server.md index 288c953ef9bf..803bac3b949f 100644 --- a/docs/generators/nodejs-express-server.md +++ b/docs/generators/nodejs-express-server.md @@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen on.| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/ocaml.md b/docs/generators/ocaml.md index ace0ed961a30..120638276739 100644 --- a/docs/generators/ocaml.md +++ b/docs/generators/ocaml.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/openapi-yaml.md b/docs/generators/openapi-yaml.md index a60117467bd4..cfbf4af70a95 100644 --- a/docs/generators/openapi-yaml.md +++ b/docs/generators/openapi-yaml.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/openapi.md b/docs/generators/openapi.md index c2636d3af5a5..9e5c7ff59738 100644 --- a/docs/generators/openapi.md +++ b/docs/generators/openapi.md @@ -26,6 +26,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/php-dt.md b/docs/generators/php-dt.md index 18ab8967f7ab..005e700d5e3a 100644 --- a/docs/generators/php-dt.md +++ b/docs/generators/php-dt.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-flight.md b/docs/generators/php-flight.md index da33756d10f6..30b2b463726d 100644 --- a/docs/generators/php-flight.md +++ b/docs/generators/php-flight.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|camelCase| diff --git a/docs/generators/php-laravel.md b/docs/generators/php-laravel.md index 99dd2adc65bf..87a5280a5502 100644 --- a/docs/generators/php-laravel.md +++ b/docs/generators/php-laravel.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-lumen.md b/docs/generators/php-lumen.md index b1855c33e3f4..84aa56bc96e1 100644 --- a/docs/generators/php-lumen.md +++ b/docs/generators/php-lumen.md @@ -36,6 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-mezzio-ph.md b/docs/generators/php-mezzio-ph.md index bd408a268a8c..c2b8013d86d9 100644 --- a/docs/generators/php-mezzio-ph.md +++ b/docs/generators/php-mezzio-ph.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-nextgen.md b/docs/generators/php-nextgen.md index 8691f4f2bc23..82b35b18e4af 100644 --- a/docs/generators/php-nextgen.md +++ b/docs/generators/php-nextgen.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |supportStreaming|Support streaming endpoint| |false| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-slim4.md b/docs/generators/php-slim4.md index e243886c016e..bbf7d79b147d 100644 --- a/docs/generators/php-slim4.md +++ b/docs/generators/php-slim4.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |psr7Implementation|Slim 4 provides its own PSR-7 implementation so that it works out of the box. However, you are free to replace Slim’s default PSR-7 objects with a third-party implementation. Ref: https://www.slimframework.com/docs/v4/concepts/value-objects.html|
**slim-psr7**
Slim PSR-7 Message implementation
**nyholm-psr7**
Nyholm PSR-7 Message implementation
**guzzle-psr7**
Guzzle PSR-7 Message implementation
**zend-diactoros**
Zend Diactoros PSR-7 Message implementation
|slim-psr7| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|camelCase| diff --git a/docs/generators/php-symfony.md b/docs/generators/php-symfony.md index 9c865996d93c..7ce296331456 100644 --- a/docs/generators/php-symfony.md +++ b/docs/generators/php-symfony.md @@ -42,6 +42,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php.md b/docs/generators/php.md index 68830fa61a66..9add8db09f7b 100644 --- a/docs/generators/php.md +++ b/docs/generators/php.md @@ -38,6 +38,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/plantuml.md b/docs/generators/plantuml.md index 6b92675c835f..caf04f734c31 100644 --- a/docs/generators/plantuml.md +++ b/docs/generators/plantuml.md @@ -25,6 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/python-aiohttp.md b/docs/generators/python-aiohttp.md index 147e816197ce..e3fa0e9b7a5e 100644 --- a/docs/generators/python-aiohttp.md +++ b/docs/generators/python-aiohttp.md @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen to in app.run| |8080| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testsUsePythonSrcRoot|generates test under the pythonSrcRoot folder.| |false| |useNose|use the nose test framework| |false| |usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false| diff --git a/docs/generators/python-blueplanet.md b/docs/generators/python-blueplanet.md index 667f50deed1f..09f941b48c42 100644 --- a/docs/generators/python-blueplanet.md +++ b/docs/generators/python-blueplanet.md @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen to in app.run| |8080| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testsUsePythonSrcRoot|generates test under the pythonSrcRoot folder.| |false| |useNose|use the nose test framework| |false| |usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false| diff --git a/docs/generators/python-fastapi.md b/docs/generators/python-fastapi.md index 6f96b6ba8960..8dcfdf670d4c 100644 --- a/docs/generators/python-fastapi.md +++ b/docs/generators/python-fastapi.md @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|directory for generated python source code| |src| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/python-flask.md b/docs/generators/python-flask.md index 684d9aa7b5e6..3e74eff31f38 100644 --- a/docs/generators/python-flask.md +++ b/docs/generators/python-flask.md @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen to in app.run| |8080| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testsUsePythonSrcRoot|generates test under the pythonSrcRoot folder.| |false| |useNose|use the nose test framework| |false| |usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false| diff --git a/docs/generators/ruby.md b/docs/generators/ruby.md index c3cd707dd0b1..e6f8577dca3c 100644 --- a/docs/generators/ruby.md +++ b/docs/generators/ruby.md @@ -39,6 +39,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useAutoload|Use autoload instead of require to load modules.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-akka-http-server.md b/docs/generators/scala-akka-http-server.md index 2da7ba01f804..26696b81d45a 100644 --- a/docs/generators/scala-akka-http-server.md +++ b/docs/generators/scala-akka-http-server.md @@ -38,6 +38,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useApachePekko|Use apache pekko-http instead of akka-http.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-akka.md b/docs/generators/scala-akka.md index 3526e6a010bd..89296a8c4272 100644 --- a/docs/generators/scala-akka.md +++ b/docs/generators/scala-akka.md @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-cask.md b/docs/generators/scala-cask.md index 76dcc6d8f51c..9f8817ece9cc 100644 --- a/docs/generators/scala-cask.md +++ b/docs/generators/scala-cask.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-gatling.md b/docs/generators/scala-gatling.md index 52af879744f7..a16121df4b0c 100644 --- a/docs/generators/scala-gatling.md +++ b/docs/generators/scala-gatling.md @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-http4s-server.md b/docs/generators/scala-http4s-server.md index 6f1f87b65acd..7bcab6632c19 100644 --- a/docs/generators/scala-http4s-server.md +++ b/docs/generators/scala-http4s-server.md @@ -28,6 +28,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceSubfolder|name of subfolder, for example to generate code in src/scala/generated| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-http4s.md b/docs/generators/scala-http4s.md index 1139666e60d0..290777918720 100644 --- a/docs/generators/scala-http4s.md +++ b/docs/generators/scala-http4s.md @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-lagom-server-deprecated.md b/docs/generators/scala-lagom-server-deprecated.md index 5c0e62eb8a44..9ff1b733e690 100644 --- a/docs/generators/scala-lagom-server-deprecated.md +++ b/docs/generators/scala-lagom-server-deprecated.md @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-pekko.md b/docs/generators/scala-pekko.md index 2e2545c22521..aab8165bb7fd 100644 --- a/docs/generators/scala-pekko.md +++ b/docs/generators/scala-pekko.md @@ -32,6 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-play-server.md b/docs/generators/scala-play-server.md index 9f8824727860..ec0c7d5a844e 100644 --- a/docs/generators/scala-play-server.md +++ b/docs/generators/scala-play-server.md @@ -34,6 +34,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|If set, wraps API return types with Futures and generates async actions.| |false| |useSwaggerUI|Add a route to /api which show your documentation in swagger-ui. Will also import needed dependencies| |true| diff --git a/docs/generators/scala-sttp.md b/docs/generators/scala-sttp.md index 0a8857baa668..39b570d9351b 100644 --- a/docs/generators/scala-sttp.md +++ b/docs/generators/scala-sttp.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |sttpClientVersion|The version of sttp client| |3.3.18| ## IMPORT MAPPING diff --git a/docs/generators/scala-sttp4-jsoniter.md b/docs/generators/scala-sttp4-jsoniter.md index b35ef71c40a7..e8fc4d71cdbe 100644 --- a/docs/generators/scala-sttp4-jsoniter.md +++ b/docs/generators/scala-sttp4-jsoniter.md @@ -33,6 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |sttpClientVersion|The version of sttp client| |4.0.23| ## IMPORT MAPPING diff --git a/docs/generators/scala-sttp4.md b/docs/generators/scala-sttp4.md index 9a246b36cec3..ed47395f0fdc 100644 --- a/docs/generators/scala-sttp4.md +++ b/docs/generators/scala-sttp4.md @@ -36,6 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |sttpClientVersion|The version of sttp client| |4.0.0-M1| ## IMPORT MAPPING diff --git a/docs/generators/scalatra.md b/docs/generators/scalatra.md index 8a3c196576bf..697884bce04a 100644 --- a/docs/generators/scalatra.md +++ b/docs/generators/scalatra.md @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scalaz.md b/docs/generators/scalaz.md index f96bbfa17862..587c85d78594 100644 --- a/docs/generators/scalaz.md +++ b/docs/generators/scalaz.md @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/spring.md b/docs/generators/spring.md index 1cda6152be9f..dab05c8fb0d9 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -97,6 +97,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| |substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| diff --git a/docs/generators/swift-combine.md b/docs/generators/swift-combine.md index 80fede94d007..9d7ab84fe78f 100644 --- a/docs/generators/swift-combine.md +++ b/docs/generators/swift-combine.md @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|Project name in Xcode| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/swift5.md b/docs/generators/swift5.md index 7c3052b6e4c9..1041d708d549 100644 --- a/docs/generators/swift5.md +++ b/docs/generators/swift5.md @@ -52,6 +52,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |responseAs|Optionally use libraries to manage response. Currently PromiseKit, RxSwift, Result, Combine, AsyncAwait are available.| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |swiftPackagePath|Set a custom source path instead of OpenAPIClient/Classes/OpenAPIs.| |null| |swiftUseApiNamespace|Flag to make all the API classes inner-class of {{projectName}}API| |null| |useBacktickEscapes|Escape reserved words using backticks (default: false)| |false| diff --git a/docs/generators/swift6.md b/docs/generators/swift6.md index c3d56f6e78d8..cf31f3ca52d9 100644 --- a/docs/generators/swift6.md +++ b/docs/generators/swift6.md @@ -54,6 +54,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |responseAs|Optionally use libraries to manage response. Currently AsyncAwait, Combine, Result, RxSwift, ObjcBlock, PromiseKit are available.| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |swiftPackagePath|Set a custom source path instead of Sources/{{projectName}}.| |null| |swiftUseApiNamespace|Flag to make all the API classes inner-class of {{projectName}}API| |null| |useBacktickEscapes|Escape reserved words using backticks (default: false)| |false| diff --git a/docs/generators/typescript-angular.md b/docs/generators/typescript-angular.md index 1b3d1fb87e38..30eb85b5f646 100644 --- a/docs/generators/typescript-angular.md +++ b/docs/generators/typescript-angular.md @@ -49,6 +49,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| diff --git a/docs/generators/typescript-aurelia.md b/docs/generators/typescript-aurelia.md index 5a75ef803916..1ac88cdca7f2 100644 --- a/docs/generators/typescript-aurelia.md +++ b/docs/generators/typescript-aurelia.md @@ -36,6 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/typescript-axios.md b/docs/generators/typescript-axios.md index 5b06ed9e205d..c192cfdbd946 100644 --- a/docs/generators/typescript-axios.md +++ b/docs/generators/typescript-axios.md @@ -40,6 +40,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |false| diff --git a/docs/generators/typescript-fetch.md b/docs/generators/typescript-fetch.md index 37762fabc0d9..bb87123aa23d 100644 --- a/docs/generators/typescript-fetch.md +++ b/docs/generators/typescript-fetch.md @@ -41,6 +41,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |true| diff --git a/docs/generators/typescript-inversify.md b/docs/generators/typescript-inversify.md index 0060e8f01eb6..2c73910b95de 100644 --- a/docs/generators/typescript-inversify.md +++ b/docs/generators/typescript-inversify.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| |usePromise|Setting this property to use promise instead of observable inside every service.| |false| diff --git a/docs/generators/typescript-jquery.md b/docs/generators/typescript-jquery.md index c7c9851e3dd0..534a5360ad48 100644 --- a/docs/generators/typescript-jquery.md +++ b/docs/generators/typescript-jquery.md @@ -38,6 +38,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/typescript-nestjs-server.md b/docs/generators/typescript-nestjs-server.md index 8017770b291d..d3968f0ceb4c 100644 --- a/docs/generators/typescript-nestjs-server.md +++ b/docs/generators/typescript-nestjs-server.md @@ -44,6 +44,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| diff --git a/docs/generators/typescript-nestjs.md b/docs/generators/typescript-nestjs.md index 5c2b8d3cd002..11dc7a9e7822 100644 --- a/docs/generators/typescript-nestjs.md +++ b/docs/generators/typescript-nestjs.md @@ -43,6 +43,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| diff --git a/docs/generators/typescript-node.md b/docs/generators/typescript-node.md index f7521e158abd..6ede8d6feb31 100644 --- a/docs/generators/typescript-node.md +++ b/docs/generators/typescript-node.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/typescript-redux-query.md b/docs/generators/typescript-redux-query.md index 55e71f159430..b1b17eb5dbc1 100644 --- a/docs/generators/typescript-redux-query.md +++ b/docs/generators/typescript-redux-query.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |true| |withInterfaces|Setting this property to true will generate interfaces next to the default class implementations.| |false| diff --git a/docs/generators/typescript-rxjs.md b/docs/generators/typescript-rxjs.md index 9a7bdcf465fa..fbfa0227e844 100644 --- a/docs/generators/typescript-rxjs.md +++ b/docs/generators/typescript-rxjs.md @@ -37,6 +37,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |withProgressSubscriber|Setting this property to true will generate API controller methods with support for subscribing to request progress.| |false| diff --git a/docs/generators/typescript.md b/docs/generators/typescript.md index 57474571765c..48a86a0771c6 100644 --- a/docs/generators/typescript.md +++ b/docs/generators/typescript.md @@ -42,6 +42,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |typescriptMajorVersion|Specify the major version of TypeScript to use in the client code. Default is 5.| |5| |useErasableSyntax|Use erasable syntax for the generated code. This is a temporary feature and will be removed in the future.| |false| diff --git a/docs/generators/wsdl-schema.md b/docs/generators/wsdl-schema.md index 4461e708ee0d..594c4eb0e815 100644 --- a/docs/generators/wsdl-schema.md +++ b/docs/generators/wsdl-schema.md @@ -30,6 +30,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |soapPath|basepath of the soap services| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useSpecifiedOperationId|whether to use autogenerated operationId's (default) or those specified in openapi spec| |null| ## IMPORT MAPPING diff --git a/docs/generators/xojo-client.md b/docs/generators/xojo-client.md index a72a3f33bf61..7df2374d34c3 100644 --- a/docs/generators/xojo-client.md +++ b/docs/generators/xojo-client.md @@ -33,6 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serializationLibrary|What serialization library to use: 'xoson' (default).| |xoson| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsAsync|Generate code that supports async operations.| |null| ## IMPORT MAPPING diff --git a/docs/generators/zapier.md b/docs/generators/zapier.md index a36029532e26..8137d73897bb 100644 --- a/docs/generators/zapier.md +++ b/docs/generators/zapier.md @@ -25,6 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| +|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING From fba4e00bd6dba9c189cb98ca6f70bb53f9c85d04 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 15:24:40 +0200 Subject: [PATCH 05/11] #6708 : Other solution without X variant and using divide directly while processing operations --- .../openapitools/codegen/CodegenConfig.java | 16 ++++++++ .../openapitools/codegen/DefaultCodegen.java | 38 +++++++------------ .../codegen/DefaultGenerator.java | 17 ++++----- .../codegen/DefaultCodegenTest.java | 36 +++++++----------- 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java index 27cd5b4ab0bd..cbd21ab7589e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java @@ -130,6 +130,22 @@ public interface CodegenConfig { CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation, List servers); + /** + * Divides an operation into one operation per content-type when it exposes several request/response + * content-types with different schemas (opt-in, see {@code splitOperationsByContentType}). Each + * returned operation is self-contained and re-enters {@link #fromOperation}. The default keeps the + * operation unchanged (returns it as a singleton). + * + * @param openAPI the OpenAPI document + * @param path the resource path + * @param httpMethod the HTTP method + * @param operation the operation to (maybe) divide + * @return the operations to generate for {@code operation} (the operation itself when not divided) + */ + default List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { + return java.util.Collections.singletonList(operation); + } + List fromSecurity(Map schemas); List fromServers(List servers); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 48ff821b614e..aa4b447157f7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1058,9 +1058,6 @@ public void postProcessResponseWithProperty(CodegenResponse response, CodegenPro public void postProcessParameter(CodegenParameter parameter) { } - /** Internal vendor extension carrying the {@code List} a divided operation expands to. */ - public static final String X_CONTENT_TYPE_VARIANTS = "x-content-type-variants"; - protected boolean splitOperationsByContentType = false; public void setSplitOperationsByContentType(boolean splitOperationsByContentType) { @@ -1068,26 +1065,20 @@ public void setSplitOperationsByContentType(boolean splitOperationsByContentType } /** - * When {@link CodegenConstants#SPLIT_OPERATIONS_BY_CONTENT_TYPE} is enabled, divides every operation whose request - * body and/or success response expose several content-types with different schemas into one - * operation per content-type (the cartesian product of the request and response axes). The variants - * are stored on the original {@link Operation} under {@link #X_CONTENT_TYPE_VARIANTS} and expanded by - * {@code DefaultGenerator}, so each one re-enters {@code fromOperation} and is typed natively by the - * target generator. This keeps the feature language-neutral: no per-language type re-derivation here. + * When {@link CodegenConstants#SPLIT_OPERATIONS_BY_CONTENT_TYPE} is enabled, divides an operation whose + * request body and/or success response expose several content-types with different schemas + * into one operation per content-type (the cartesian product of the request and response axes, + * deduplicated by schema). Each variant is narrowed to a single content-type on each axis with a typed, + * collision-free operationId; {@code DefaultGenerator} processes each so it re-enters + * {@code fromOperation} and is typed natively by the target generator. This keeps the feature + * language-neutral: no per-language type re-derivation here. Returns the operation as a singleton when + * the option is off or no division applies. */ - private void divideOperationsByContentType(OpenAPI openAPI) { - if (!splitOperationsByContentType || openAPI.getPaths() == null) { - return; - } - for (Map.Entry pathEntry : openAPI.getPaths().entrySet()) { - String path = pathEntry.getKey(); - for (Map.Entry opEntry : pathEntry.getValue().readOperationsMap().entrySet()) { - divideOperationByContentType(openAPI, path, opEntry.getKey().name().toLowerCase(Locale.ROOT), opEntry.getValue()); - } + @Override + public List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { + if (!splitOperationsByContentType || operation == null) { + return Collections.singletonList(operation); } - } - - private void divideOperationByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { List requestAxis = requestContentTypeAxis(openAPI, operation); String targetResponseCode = findMultiSchemaSuccessResponseCode(openAPI, operation); ApiResponse targetResponse = targetResponseCode == null ? null @@ -1097,7 +1088,7 @@ private void divideOperationByContentType(OpenAPI openAPI, String path, String h boolean requestSplit = requestAxis.size() > 1; boolean responseSplit = responseAxis.size() > 1; if (!requestSplit && !responseSplit) { - return; // single content-type on both axes: nothing to divide + return Collections.singletonList(operation); // single content-type on both axes: nothing to divide } String baseId = getOrGenerateOperationId(operation, path, httpMethod); @@ -1110,7 +1101,7 @@ private void divideOperationByContentType(OpenAPI openAPI, String path, String h targetResponseCode, targetResponse)); } } - operation.addExtension(X_CONTENT_TYPE_VARIANTS, variants); + return variants; } /** Distinct (by resolved schema) request-body content-types, JSON first; a singleton list if not split. */ @@ -1265,7 +1256,6 @@ private static String subtypeToken(String mediaType) { @Override @SuppressWarnings("unused") public void preprocessOpenAPI(OpenAPI openAPI) { - divideOperationsByContentType(openAPI); if (useOneOfInterfaces && openAPI.getComponents() != null) { // we process the openapi schema here to find oneOf schemas and create interface models for them Map schemas = new HashMap<>(openAPI.getComponents().getSchemas()); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java index eea6d8639e28..b750ee2167bb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java @@ -1521,16 +1521,15 @@ private void processOperation(String resourcePath, String httpMethod, Operation return; } - // splitOperationsByContentType: an operation divided by content-type expands into its variants, - // each a self-contained single-content-type Operation that re-enters the normal pipeline. - if (operation.getExtensions() != null) { - Object variants = operation.getExtensions().get(DefaultCodegen.X_CONTENT_TYPE_VARIANTS); - if (variants instanceof List && !((List) variants).isEmpty()) { - for (Object variant : (List) variants) { - processOperation(resourcePath, httpMethod, (Operation) variant, operations, path); - } - return; + // splitOperationsByContentType: an operation that exposes several content-types with different + // schemas is divided into one self-contained single-content-type Operation per content-type, each + // re-entering the pipeline so it is typed natively by the generator. + List contentTypeVariants = config.divideOperationsByContentType(openAPI, resourcePath, httpMethod, operation); + if (contentTypeVariants.size() > 1) { + for (Operation variant : contentTypeVariants) { + processOperation(resourcePath, httpMethod, variant, operations, path); } + return; } if (GlobalSettings.getProperty("debugOperations") != null) { diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index 9cfdc868a0dd..acdb0efcadbc 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -5231,11 +5231,10 @@ public void splitOperationsByContentType() { codegen.setSplitOperationsByContentType(true); OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/issue6708-split-by-content-type.yaml"); - codegen.preprocessOpenAPI(openAPI); - // POST /reports: request {json -> Report, xml -> ReportXml} x response {json -> Receipt, pdf -> binary} // is divided into the cartesian product, each variant narrowed to a single content-type on both axes. - List postVariants = contentTypeVariants(openAPI.getPaths().get("/reports").getPost()); + Operation post = openAPI.getPaths().get("/reports").getPost(); + List postVariants = codegen.divideOperationsByContentType(openAPI, "/reports", "post", post); assertThat(postVariants).extracting(Operation::getOperationId) .containsExactlyInAnyOrder("createReportWithJsonAsJson", "createReportWithJsonAsPdf", "createReportWithXmlAsJson", "createReportWithXmlAsPdf"); @@ -5245,8 +5244,9 @@ public void splitOperationsByContentType() { } // GET /reports/{id}: no request body, response {json -> Report, directlog -> binary} => 2 variants. - List getVariants = contentTypeVariants(openAPI.getPaths().get("/reports/{id}").getGet()); - assertThat(getVariants).extracting(Operation::getOperationId) + Operation get = openAPI.getPaths().get("/reports/{id}").getGet(); + assertThat(codegen.divideOperationsByContentType(openAPI, "/reports/{id}", "get", get)) + .extracting(Operation::getOperationId) .containsExactlyInAnyOrder("getReportAsJson", "getReportAsDirectlog"); } @@ -5256,13 +5256,12 @@ public void splitOperationsByContentTypeLeavesUnambiguousOperationsUntouched() { codegen.setSplitOperationsByContentType(true); OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/petstore.yaml"); - codegen.preprocessOpenAPI(openAPI); - - // petstore has no operation exposing several content-types with different schemas: nothing is divided. - boolean anyDivided = openAPI.getPaths().values().stream() - .flatMap(path -> path.readOperations().stream()) - .anyMatch(op -> op.getExtensions() != null && op.getExtensions().containsKey(DefaultCodegen.X_CONTENT_TYPE_VARIANTS)); - assertThat(anyDivided).isFalse(); + // petstore has no operation exposing several content-types with different schemas: every operation + // is returned unchanged (as a singleton). + openAPI.getPaths().forEach((path, pathItem) -> + pathItem.readOperationsMap().forEach((method, operation) -> + assertThat(codegen.divideOperationsByContentType(openAPI, path, method.name(), operation)) + .containsExactly(operation))); } @Test @@ -5271,22 +5270,15 @@ public void splitOperationsByContentTypeUsesTheMethodResponse() { codegen.setSplitOperationsByContentType(true); OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/issue6708-method-response-target.yaml"); - codegen.preprocessOpenAPI(openAPI); - // /a: the method response (200, the lowest 2xx) is multi-content -> split by content-type. - assertThat(contentTypeVariants(openAPI.getPaths().get("/a").getGet())) + Operation getA = openAPI.getPaths().get("/a").getGet(); + assertThat(codegen.divideOperationsByContentType(openAPI, "/a", "get", getA)) .extracting(Operation::getOperationId) .containsExactlyInAnyOrder("getAAsJson", "getAAsPdf"); // /b: only the non-method response (206) is multi-content; the method response (200) is single, // so the operation is left untouched - the generator derives the return type from 200 only. Operation getB = openAPI.getPaths().get("/b").getGet(); - assertThat(getB.getExtensions() != null - && getB.getExtensions().containsKey(DefaultCodegen.X_CONTENT_TYPE_VARIANTS)).isFalse(); - } - - @SuppressWarnings("unchecked") - private static List contentTypeVariants(Operation operation) { - return (List) operation.getExtensions().get(DefaultCodegen.X_CONTENT_TYPE_VARIANTS); + assertThat(codegen.divideOperationsByContentType(openAPI, "/b", "get", getB)).containsExactly(getB); } } From ace0d17c061548940b92fb642e1d50c91d38d20c Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 15:41:56 +0200 Subject: [PATCH 06/11] #6708 Simplification of code, removing useless "findMultiSchemaSuccessResponseCode" --- .../openapitools/codegen/DefaultCodegen.java | 46 +++++-------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index aa4b447157f7..786962d3924f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1079,11 +1079,15 @@ public List divideOperationsByContentType(OpenAPI openAPI, String pat if (!splitOperationsByContentType || operation == null) { return Collections.singletonList(operation); } - List requestAxis = requestContentTypeAxis(openAPI, operation); - String targetResponseCode = findMultiSchemaSuccessResponseCode(openAPI, operation); - ApiResponse targetResponse = targetResponseCode == null ? null - : ModelUtils.getReferencedApiResponse(openAPI, operation.getResponses().get(targetResponseCode)); - List responseAxis = axisOf(targetResponse == null ? null : targetResponse.getContent()); + RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); + List requestAxis = axisOf(requestBody == null ? null : requestBody.getContent()); + + // Only the response the generator derives the return type from (the method response) is split, so the + // variants' return types and Accept headers stay consistent (see findMethodResponse). + String methodResponseCode = operation.getResponses() == null ? null : findMethodResponseCode(operation.getResponses()); + ApiResponse methodResponse = methodResponseCode == null ? null + : ModelUtils.getReferencedApiResponse(openAPI, operation.getResponses().get(methodResponseCode)); + List responseAxis = axisOf(methodResponse == null ? null : methodResponse.getContent()); boolean requestSplit = requestAxis.size() > 1; boolean responseSplit = responseAxis.size() > 1; @@ -1098,18 +1102,12 @@ public List divideOperationsByContentType(OpenAPI openAPI, String pat variants.add(buildOperationVariant(openAPI, operation, baseId, requestSplit ? requestMediaType : null, responseSplit ? responseMediaType : null, - targetResponseCode, targetResponse)); + methodResponseCode, methodResponse)); } } return variants; } - /** Distinct (by resolved schema) request-body content-types, JSON first; a singleton list if not split. */ - private List requestContentTypeAxis(OpenAPI openAPI, Operation operation) { - RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); - return axisOf(requestBody == null ? null : requestBody.getContent()); - } - /** * The media-types of {@code content} deduplicated by resolved schema (so two media-types mapping to * the same schema collapse), JSON-first for determinism. Returns a singleton {@code [null]} when there @@ -1141,28 +1139,6 @@ private List axisOf(Content content) { return ordered; } - /** First 2xx response exposing at least two content-types with different schemas, or {@code null}. */ - private String findMultiSchemaSuccessResponseCode(OpenAPI openAPI, Operation operation) { - if (operation.getResponses() == null) { - return null; - } - // Only split the response the generator actually derives the return type from, so the variants' - // return types and Accept headers stay consistent (see findMethodResponse). - String code = findMethodResponseCode(operation.getResponses()); - if (code == null) { - return null; - } - ApiResponse response = ModelUtils.getReferencedApiResponse(openAPI, operation.getResponses().get(code)); - Content content = response == null ? null : response.getContent(); - if (content == null || content.size() < 2) { - return null; - } - long distinctSchemas = content.values().stream() - .map(mt -> schemaKey(mt == null ? null : mt.getSchema())) - .distinct().count(); - return distinctSchemas >= 2 ? code : null; - } - /** * Builds one operation variant narrowed to a single request and/or response media-type (a {@code null} * media-type leaves that axis untouched), with a typed, collision-free operationId. @@ -1237,7 +1213,7 @@ private static String schemaKey(Schema schema) { return schema.get$ref(); } StringBuilder key = new StringBuilder(); - key.append(schema.getType()).append('|').append(schema.getFormat()); + key.append(ModelUtils.getType(schema)).append('|').append(schema.getFormat()); if (schema.getItems() != null) { key.append("|items=").append(schemaKey(schema.getItems())); } From 398caf056e10d6da16113a422a4bb558dcca774f Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 3 Jun 2026 16:06:14 +0200 Subject: [PATCH 07/11] #6708 : Remove default implemenation in Interface. No sense because the default implementation is in CodegenDefault --- .../main/java/org/openapitools/codegen/CodegenConfig.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java index cbd21ab7589e..4a7f98c5b02d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java @@ -133,8 +133,8 @@ public interface CodegenConfig { /** * Divides an operation into one operation per content-type when it exposes several request/response * content-types with different schemas (opt-in, see {@code splitOperationsByContentType}). Each - * returned operation is self-contained and re-enters {@link #fromOperation}. The default keeps the - * operation unchanged (returns it as a singleton). + * returned operation is self-contained and re-enters {@link #fromOperation}. When the option is off or + * no division applies, the operation is returned unchanged (as a singleton). * * @param openAPI the OpenAPI document * @param path the resource path @@ -142,9 +142,7 @@ public interface CodegenConfig { * @param operation the operation to (maybe) divide * @return the operations to generate for {@code operation} (the operation itself when not divided) */ - default List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { - return java.util.Collections.singletonList(operation); - } + List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation); List fromSecurity(Map schemas); From d2cafed477c490e8c099a041bef50c9ee346e731 Mon Sep 17 00:00:00 2001 From: Antoine Date: Fri, 7 Aug 2026 10:55:20 +0200 Subject: [PATCH 08/11] #6708 : make splitOperationsByContentType a global property, merged back per generator Following the review on #23935: the option was a CLI option repeated in every generator that wanted it. It is now a global property, read once from GlobalSettings in DefaultCodegen.processOpts, like skipFormModel already is. DefaultGenerator.processOperation asks the config to divide an operation before processing it, and DefaultCodegen implements the division once, language neutrally: an operation whose request body and/or method response expose several content-types with different schemas becomes one operation per (request, response) content-type pair, each narrowed to a single media-type and given a typed, collision-free operationId. Every variant re-enters fromOperation, so its body and return types are resolved natively by the target generator - the shared code re-derives no types of its own. Each variant also carries x-content-type-variant-* extensions recording where it sits in the matrix, so a generator able to express the whole matrix in a single construct can merge the variants back instead of emitting one method per combination. typescript-fetch does: the variants collapse into one method whose request type is a union discriminated by `contentType`, and whose return type is picked by overloads on `accept`, each branch keeping the types the split resolved for it. A generator that does not merge simply gets the separate methods, which is what a statically-typed language needs anyway. With the option off, divideOperationsByContentType returns the operation as a singleton and the merge returns immediately: regenerating the 19 typescript-fetch sample configs produces a byte-identical tree. --- docs/generators/ada-server.md | 1 - docs/generators/ada.md | 1 - docs/generators/android.md | 1 - docs/generators/apache2.md | 1 - docs/generators/apex.md | 1 - docs/generators/asciidoc.md | 1 - docs/generators/aspnet-fastendpoints.md | 1 - docs/generators/avro-schema.md | 1 - docs/generators/bash.md | 1 - docs/generators/c.md | 1 - docs/generators/clojure.md | 1 - docs/generators/cpp-httplib-server.md | 1 - docs/generators/cpp-qt-client.md | 1 - docs/generators/cpp-qt-qhttpengine-server.md | 1 - docs/generators/cpp-tiny.md | 1 - docs/generators/cpp-tizen.md | 1 - docs/generators/cpp-ue4.md | 1 - docs/generators/crystal.md | 1 - docs/generators/cwiki.md | 1 - docs/generators/dart-dio.md | 1 - docs/generators/dart.md | 1 - docs/generators/dynamic-html.md | 1 - docs/generators/elixir.md | 1 - docs/generators/fsharp-functions.md | 1 - docs/generators/gdscript.md | 1 - docs/generators/groovy.md | 1 - docs/generators/haskell-http-client.md | 1 - docs/generators/haskell-yesod.md | 1 - docs/generators/haskell.md | 1 - docs/generators/html.md | 1 - docs/generators/html2.md | 1 - docs/generators/java-camel.md | 1 - docs/generators/java-dubbo.md | 1 - docs/generators/java-helidon-client.md | 1 - docs/generators/java-helidon-server.md | 1 - docs/generators/java-inflector.md | 1 - docs/generators/java-micronaut-client.md | 1 - docs/generators/java-micronaut-server.md | 1 - docs/generators/java-microprofile.md | 1 - docs/generators/java-msf4j.md | 1 - docs/generators/java-pkmst.md | 1 - docs/generators/java-play-framework.md | 1 - docs/generators/java-undertow-server.md | 1 - docs/generators/java-vertx-web.md | 1 - docs/generators/java-vertx.md | 1 - docs/generators/java-wiremock.md | 1 - docs/generators/java.md | 1 - .../javascript-apollo-deprecated.md | 1 - docs/generators/javascript-closure-angular.md | 1 - docs/generators/javascript-flowtyped.md | 1 - docs/generators/javascript.md | 1 - docs/generators/jaxrs-cxf-cdi.md | 1 - docs/generators/jaxrs-cxf-client.md | 1 - docs/generators/jaxrs-cxf-extended.md | 1 - docs/generators/jaxrs-cxf.md | 1 - docs/generators/jaxrs-jersey.md | 1 - docs/generators/jaxrs-resteasy-eap.md | 1 - docs/generators/jaxrs-resteasy.md | 1 - docs/generators/jaxrs-spec.md | 1 - docs/generators/jmeter.md | 1 - docs/generators/k6.md | 1 - docs/generators/markdown.md | 1 - docs/generators/nim.md | 1 - docs/generators/nodejs-express-server.md | 1 - docs/generators/ocaml.md | 1 - docs/generators/openapi-yaml.md | 1 - docs/generators/openapi.md | 1 - docs/generators/php-dt.md | 1 - docs/generators/php-flight.md | 1 - docs/generators/php-laravel.md | 1 - docs/generators/php-lumen.md | 1 - docs/generators/php-mezzio-ph.md | 1 - docs/generators/php-nextgen.md | 1 - docs/generators/php-slim4.md | 1 - docs/generators/php-symfony.md | 1 - docs/generators/php.md | 1 - docs/generators/plantuml.md | 1 - docs/generators/python-aiohttp.md | 1 - docs/generators/python-blueplanet.md | 1 - docs/generators/python-fastapi.md | 1 - docs/generators/python-flask.md | 1 - docs/generators/ruby.md | 1 - docs/generators/scala-akka-http-server.md | 1 - docs/generators/scala-akka.md | 1 - docs/generators/scala-cask.md | 1 - docs/generators/scala-gatling.md | 1 - docs/generators/scala-http4s-server.md | 1 - docs/generators/scala-http4s.md | 1 - .../scala-lagom-server-deprecated.md | 1 - docs/generators/scala-pekko.md | 1 - docs/generators/scala-play-server.md | 1 - docs/generators/scala-sttp.md | 1 - docs/generators/scala-sttp4-jsoniter.md | 1 - docs/generators/scala-sttp4.md | 1 - docs/generators/scalatra.md | 1 - docs/generators/scalaz.md | 1 - docs/generators/spring.md | 1 - docs/generators/swift-combine.md | 1 - docs/generators/swift5.md | 1 - docs/generators/swift6.md | 1 - docs/generators/typescript-angular.md | 1 - docs/generators/typescript-aurelia.md | 1 - docs/generators/typescript-axios.md | 1 - docs/generators/typescript-fetch.md | 1 - docs/generators/typescript-inversify.md | 1 - docs/generators/typescript-jquery.md | 1 - docs/generators/typescript-nestjs-server.md | 1 - docs/generators/typescript-nestjs.md | 1 - docs/generators/typescript-node.md | 1 - docs/generators/typescript-redux-query.md | 1 - docs/generators/typescript-rxjs.md | 1 - docs/generators/typescript.md | 1 - docs/generators/wsdl-schema.md | 1 - docs/generators/xojo-client.md | 1 - docs/generators/zapier.md | 1 - docs/global-properties.md | 49 +++ .../openapitools/codegen/CodegenConfig.java | 9 +- .../codegen/CodegenConstants.java | 17 +- .../openapitools/codegen/DefaultCodegen.java | 204 ++++++++---- .../TypeScriptFetchClientCodegen.java | 288 ++++++++++++++++- .../codegen/utils/ModelUtils.java | 41 --- .../resources/typescript-fetch/apis.mustache | 293 +++++++++++------- .../apisContentTypeVariantBody.mustache | 33 ++ .../typescript-fetch/apisFormParams.mustache | 67 ++++ .../apisOperationEnum.mustache | 28 ++ .../apisRequestBodyValue.mustache | 3 + .../apisResponseVariantValue.mustache | 42 +++ .../typescript-fetch/runtime.mustache | 15 + .../codegen/DefaultCodegenTest.java | 49 +++ .../options/BashClientOptionsProvider.java | 1 - .../options/DartClientOptionsProvider.java | 1 - .../options/DartDioClientOptionsProvider.java | 1 - .../options/ElixirClientOptionsProvider.java | 1 - .../HaskellServantOptionsProvider.java | 1 - .../HaskellYesodServerOptionsProvider.java | 1 - .../options/PhpClientOptionsProvider.java | 1 - .../PhpLumenServerOptionsProvider.java | 1 - .../PhpSlim4ServerOptionsProvider.java | 1 - .../options/RubyClientOptionsProvider.java | 1 - .../ScalaAkkaClientOptionsProvider.java | 1 - .../options/Swift5OptionsProvider.java | 1 - .../Swift6ClientCodegenOptionsProvider.java | 1 - ...TypeScriptSharedClientOptionsProvider.java | 1 - .../options/XojoClientOptionsProvider.java | 1 - .../TypeScriptFetchClientCodegenTest.java | 285 +++++++++++++++++ ...6708-split-by-content-type-enum-param.yaml | 34 ++ .../issue6708-split-by-content-type-form.yaml | 64 ++++ ...-split-by-content-type-name-collision.yaml | 42 +++ ...lit-by-content-type-optional-response.yaml | 36 +++ ...8-split-by-content-type-required-body.yaml | 75 +++++ ...8-split-by-content-type-required-form.yaml | 38 +++ ...08-split-by-content-type-variant-enum.yaml | 40 +++ 152 files changed, 1529 insertions(+), 353 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache create mode 100644 modules/openapi-generator/src/main/resources/typescript-fetch/apisFormParams.mustache create mode 100644 modules/openapi-generator/src/main/resources/typescript-fetch/apisOperationEnum.mustache create mode 100644 modules/openapi-generator/src/main/resources/typescript-fetch/apisRequestBodyValue.mustache create mode 100644 modules/openapi-generator/src/main/resources/typescript-fetch/apisResponseVariantValue.mustache create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-enum-param.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-form.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-name-collision.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-optional-response.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-body.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-form.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-variant-enum.yaml diff --git a/docs/generators/ada-server.md b/docs/generators/ada-server.md index e7cd55677774..ef255ad0a889 100644 --- a/docs/generators/ada-server.md +++ b/docs/generators/ada-server.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|GNAT project name| |defaultProject| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/ada.md b/docs/generators/ada.md index e3e7fb9d6dd0..dbe8100ed6b4 100644 --- a/docs/generators/ada.md +++ b/docs/generators/ada.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|GNAT project name| |defaultProject| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/android.md b/docs/generators/android.md index decb52bfbecd..eae5d263ac86 100644 --- a/docs/generators/android.md +++ b/docs/generators/android.md @@ -38,7 +38,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useAndroidMavenGradlePlugin|A flag to toggle android-maven gradle plugin.| |true| ## IMPORT MAPPING diff --git a/docs/generators/apache2.md b/docs/generators/apache2.md index a98b5f92fa82..db059f001c21 100644 --- a/docs/generators/apache2.md +++ b/docs/generators/apache2.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |userInfoPath|Path to the user and group files| |null| ## IMPORT MAPPING diff --git a/docs/generators/apex.md b/docs/generators/apex.md index df64fe7c706d..ef0cde0019f2 100644 --- a/docs/generators/apex.md +++ b/docs/generators/apex.md @@ -30,7 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/asciidoc.md b/docs/generators/asciidoc.md index 63901722bb80..4fa26626bee2 100644 --- a/docs/generators/asciidoc.md +++ b/docs/generators/asciidoc.md @@ -40,7 +40,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |specDir|path with includable markup spec files (e.g. handwritten additional docs, default: ..)| |..| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useIntroduction|use introduction section, rather than an initial abstract (default: false)| |false| |useMethodAndPath|Use HTTP method and path as operation heading, instead of operation id (default: false)| |false| |useTableTitles|Use titles for tables, rather than wrapping tables instead their own section (default: false)| |false| diff --git a/docs/generators/aspnet-fastendpoints.md b/docs/generators/aspnet-fastendpoints.md index 53998a025061..b272b42a7e3b 100644 --- a/docs/generators/aspnet-fastendpoints.md +++ b/docs/generators/aspnet-fastendpoints.md @@ -30,7 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |solutionGuid|The solution GUID to be used in the solution file (auto generated if not provided)| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useApiVersioning|Enable API versioning (https://fast-endpoints.com/docs/api-versioning).| |false| |useAuthentication|Enable authentication (https://fast-endpoints.com/docs/security).| |false| |useProblemDetails|Enable RFC compatible error responses (https://fast-endpoints.com/docs/configuration-settings#rfc7807-rfc9457-compatible-problem-details).| |false| diff --git a/docs/generators/avro-schema.md b/docs/generators/avro-schema.md index 60b8c9530d37..f409b796e8d3 100644 --- a/docs/generators/avro-schema.md +++ b/docs/generators/avro-schema.md @@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useLogicalTypes|Use logical types for fields, when matching OpenAPI types. Currently supported: `date-time`, `date`.| |false| ## IMPORT MAPPING diff --git a/docs/generators/bash.md b/docs/generators/bash.md index 7f69d1c804d9..e5d12261d54f 100644 --- a/docs/generators/bash.md +++ b/docs/generators/bash.md @@ -34,7 +34,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |scriptName|The name of the script that will be generated (e.g. petstore-cli)| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/c.md b/docs/generators/c.md index 06f98a2f5a51..f53d973c2731 100644 --- a/docs/generators/c.md +++ b/docs/generators/c.md @@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useJsonUnformatted|Use cJSON_PrintUnformatted instead of cJSON_Print when creating the JSON string.| |false| ## IMPORT MAPPING diff --git a/docs/generators/clojure.md b/docs/generators/clojure.md index a6ec821f805f..d152d949d75b 100644 --- a/docs/generators/clojure.md +++ b/docs/generators/clojure.md @@ -33,7 +33,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectVersion|version of the project (Default: using info.version or "1.0.0")| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/cpp-httplib-server.md b/docs/generators/cpp-httplib-server.md index 2fe50b6920fd..8cdbe5e96c72 100644 --- a/docs/generators/cpp-httplib-server.md +++ b/docs/generators/cpp-httplib-server.md @@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-qt-client.md b/docs/generators/cpp-qt-client.md index 8190b26f5091..7ca05b6930a9 100644 --- a/docs/generators/cpp-qt-client.md +++ b/docs/generators/cpp-qt-client.md @@ -34,7 +34,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-qt-qhttpengine-server.md b/docs/generators/cpp-qt-qhttpengine-server.md index b353ad978949..9fbf3fca8020 100644 --- a/docs/generators/cpp-qt-qhttpengine-server.md +++ b/docs/generators/cpp-qt-qhttpengine-server.md @@ -30,7 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-tiny.md b/docs/generators/cpp-tiny.md index aba436b1f2ee..97e0e7eea4f3 100644 --- a/docs/generators/cpp-tiny.md +++ b/docs/generators/cpp-tiny.md @@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-tizen.md b/docs/generators/cpp-tizen.md index fa8a96821286..58f0390bd8b8 100644 --- a/docs/generators/cpp-tizen.md +++ b/docs/generators/cpp-tizen.md @@ -27,7 +27,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| ## IMPORT MAPPING diff --git a/docs/generators/cpp-ue4.md b/docs/generators/cpp-ue4.md index f512560586e0..b8c44498f35e 100644 --- a/docs/generators/cpp-ue4.md +++ b/docs/generators/cpp-ue4.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |unrealModuleName|Name of the generated unreal module (optional)| |OpenAPI| |variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true| diff --git a/docs/generators/crystal.md b/docs/generators/crystal.md index 56b388bee8f3..cf41d7e11ab0 100644 --- a/docs/generators/crystal.md +++ b/docs/generators/crystal.md @@ -36,7 +36,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |shardVersion|shard version.| |1.0.0| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/cwiki.md b/docs/generators/cwiki.md index 94bc417a0813..058e50555b43 100644 --- a/docs/generators/cwiki.md +++ b/docs/generators/cwiki.md @@ -35,7 +35,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/dart-dio.md b/docs/generators/dart-dio.md index 9ef64a28c536..21a5a07357c7 100644 --- a/docs/generators/dart-dio.md +++ b/docs/generators/dart-dio.md @@ -42,7 +42,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useEnumExtension|Allow the 'x-enum-values' extension for enums| |false| |useOptional|Use Optional<T> to distinguish absent, null, and present for optional fields (Dart 3+)| |false| diff --git a/docs/generators/dart.md b/docs/generators/dart.md index 6e0fd3bbd625..a06c695af0cf 100644 --- a/docs/generators/dart.md +++ b/docs/generators/dart.md @@ -38,7 +38,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useEnumExtension|Allow the 'x-enum-values' extension for enums| |false| |useOptional|Use Optional<T> to distinguish absent, null, and present for optional fields (Dart 3+)| |false| diff --git a/docs/generators/dynamic-html.md b/docs/generators/dynamic-html.md index 3f4685332148..569cd7154ced 100644 --- a/docs/generators/dynamic-html.md +++ b/docs/generators/dynamic-html.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/elixir.md b/docs/generators/elixir.md index 40cff3895277..f235da179c5a 100644 --- a/docs/generators/elixir.md +++ b/docs/generators/elixir.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/fsharp-functions.md b/docs/generators/fsharp-functions.md index fc4712845e25..4e589d22802e 100644 --- a/docs/generators/fsharp-functions.md +++ b/docs/generators/fsharp-functions.md @@ -35,7 +35,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |OpenAPI/src| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/gdscript.md b/docs/generators/gdscript.md index f9fe5a99d743..ee3abee25371 100644 --- a/docs/generators/gdscript.md +++ b/docs/generators/gdscript.md @@ -30,7 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/groovy.md b/docs/generators/groovy.md index c1a109e5eabb..a7125c0350b4 100644 --- a/docs/generators/groovy.md +++ b/docs/generators/groovy.md @@ -67,7 +67,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/groovy| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/haskell-http-client.md b/docs/generators/haskell-http-client.md index fea5718ab076..4a06d06b7373 100644 --- a/docs/generators/haskell-http-client.md +++ b/docs/generators/haskell-http-client.md @@ -46,7 +46,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |requestType|Set the name of the type used to generate requests| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |strictFields|Add strictness annotations to all model fields| |true| |useKatip|Sets the default value for the UseKatip cabal flag. If true, the katip package provides logging instead of monad-logger| |true| diff --git a/docs/generators/haskell-yesod.md b/docs/generators/haskell-yesod.md index 21a382cb630f..3d60cf095d8f 100644 --- a/docs/generators/haskell-yesod.md +++ b/docs/generators/haskell-yesod.md @@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|name of the project (Default: generated from info.title or "openapi-haskell-yesod-server")| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/haskell.md b/docs/generators/haskell.md index 7edb032a956c..192d9b58ee56 100644 --- a/docs/generators/haskell.md +++ b/docs/generators/haskell.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serveStatic|serve will serve files from the directory 'static'.| |true| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useCustomMonad|use a custom monad instead of the default Handler| |false| ## IMPORT MAPPING diff --git a/docs/generators/html.md b/docs/generators/html.md index 7a7bb941fd76..aa91c8e8daf2 100644 --- a/docs/generators/html.md +++ b/docs/generators/html.md @@ -35,7 +35,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/html2.md b/docs/generators/html2.md index 26d4edc7f09f..91d5b9e51d3b 100644 --- a/docs/generators/html2.md +++ b/docs/generators/html2.md @@ -39,7 +39,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |pythonPackageName|package name for generated python code| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md index 5e68a5b62eb9..b67c8e111a69 100644 --- a/docs/generators/java-camel.md +++ b/docs/generators/java-camel.md @@ -104,7 +104,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| |substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| diff --git a/docs/generators/java-dubbo.md b/docs/generators/java-dubbo.md index 193557fd7d32..d39495d8a2e0 100644 --- a/docs/generators/java-dubbo.md +++ b/docs/generators/java-dubbo.md @@ -77,7 +77,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|API title name| |null| |useGenericResponse|Use generic response wrapper| |false| diff --git a/docs/generators/java-helidon-client.md b/docs/generators/java-helidon-client.md index 7d5b13102c82..cab0e57ada6f 100644 --- a/docs/generators/java-helidon-client.md +++ b/docs/generators/java-helidon-client.md @@ -64,7 +64,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-helidon-server.md b/docs/generators/java-helidon-server.md index 6870f3277754..e817d1e1e2b3 100644 --- a/docs/generators/java-helidon-server.md +++ b/docs/generators/java-helidon-server.md @@ -65,7 +65,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useAbstractClass|Whether to generate abstract classes for REST API instead of interfaces.| |false| |useBeanValidation|Use Bean Validation| |false| diff --git a/docs/generators/java-inflector.md b/docs/generators/java-inflector.md index 29c14fa22f45..3cc8851281ed 100644 --- a/docs/generators/java-inflector.md +++ b/docs/generators/java-inflector.md @@ -69,7 +69,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-micronaut-client.md b/docs/generators/java-micronaut-client.md index 5a7972e4cb6e..5b0fcc3ab460 100644 --- a/docs/generators/java-micronaut-client.md +++ b/docs/generators/java-micronaut-client.md @@ -84,7 +84,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |test|Specify which test tool to generate files for|
**junit**
Use JUnit as test tool
**spock**
Use Spock as test tool
|junit| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|Client service name| |null| diff --git a/docs/generators/java-micronaut-server.md b/docs/generators/java-micronaut-server.md index c7b3d31eb7f0..eb6e68a82e57 100644 --- a/docs/generators/java-micronaut-server.md +++ b/docs/generators/java-micronaut-server.md @@ -82,7 +82,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |test|Specify which test tool to generate files for|
**junit**
Use JUnit as test tool
**spock**
Use Spock as test tool
|junit| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|Client service name| |null| diff --git a/docs/generators/java-microprofile.md b/docs/generators/java-microprofile.md index 6070f42306a6..f6a93340b5b0 100644 --- a/docs/generators/java-microprofile.md +++ b/docs/generators/java-microprofile.md @@ -89,7 +89,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportStreaming|Support streaming endpoint (beta)| |false| |supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false| |supportVertxFuture|Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.| |false| diff --git a/docs/generators/java-msf4j.md b/docs/generators/java-msf4j.md index 337a176b9ce3..b806ca5901a3 100644 --- a/docs/generators/java-msf4j.md +++ b/docs/generators/java-msf4j.md @@ -72,7 +72,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/java-pkmst.md b/docs/generators/java-pkmst.md index 37a45edca5cc..dbc4a66daef9 100644 --- a/docs/generators/java-pkmst.md +++ b/docs/generators/java-pkmst.md @@ -73,7 +73,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |springBootAdminUri|Spring-Boot URI| |null| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |null| diff --git a/docs/generators/java-play-framework.md b/docs/generators/java-play-framework.md index 1d9611442989..0eb293d1f84b 100644 --- a/docs/generators/java-play-framework.md +++ b/docs/generators/java-play-framework.md @@ -73,7 +73,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |/app| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|Support Async operations| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|server title name or client service name| |openapi-java-playframework| diff --git a/docs/generators/java-undertow-server.md b/docs/generators/java-undertow-server.md index 066ad13f6dfc..3e41d2e24485 100644 --- a/docs/generators/java-undertow-server.md +++ b/docs/generators/java-undertow-server.md @@ -69,7 +69,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-vertx-web.md b/docs/generators/java-vertx-web.md index d4587546d9cf..2530cd52bdf9 100644 --- a/docs/generators/java-vertx-web.md +++ b/docs/generators/java-vertx-web.md @@ -69,7 +69,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-vertx.md b/docs/generators/java-vertx.md index 1ad574964e95..cb91eeb2c753 100644 --- a/docs/generators/java-vertx.md +++ b/docs/generators/java-vertx.md @@ -71,7 +71,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java-wiremock.md b/docs/generators/java-wiremock.md index 652a1532a64c..c9ae878a03f5 100644 --- a/docs/generators/java-wiremock.md +++ b/docs/generators/java-wiremock.md @@ -69,7 +69,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false| |useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false| diff --git a/docs/generators/java.md b/docs/generators/java.md index ca2cc730606e..780b1aca9bf6 100644 --- a/docs/generators/java.md +++ b/docs/generators/java.md @@ -89,7 +89,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportStreaming|Support streaming endpoint (beta)| |false| |supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false| |supportVertxFuture|Also generate api methods that return a vertx Future instead of taking a callback. Only `vertx` supports this option. Requires vertx 4 or greater.| |false| diff --git a/docs/generators/javascript-apollo-deprecated.md b/docs/generators/javascript-apollo-deprecated.md index 5f9f9e858e17..d416fc0afd83 100644 --- a/docs/generators/javascript-apollo-deprecated.md +++ b/docs/generators/javascript-apollo-deprecated.md @@ -40,7 +40,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useInheritance|use JavaScript prototype chains & delegation for inheritance| |true| |usePromises|use Promises as return values from the client API, instead of superagent callbacks| |false| diff --git a/docs/generators/javascript-closure-angular.md b/docs/generators/javascript-closure-angular.md index 24fc66c37f16..fb69b29ef077 100644 --- a/docs/generators/javascript-closure-angular.md +++ b/docs/generators/javascript-closure-angular.md @@ -27,7 +27,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useEs6|use ES6 templates| |false| ## IMPORT MAPPING diff --git a/docs/generators/javascript-flowtyped.md b/docs/generators/javascript-flowtyped.md index 84f9c23856fa..9c194758ece0 100644 --- a/docs/generators/javascript-flowtyped.md +++ b/docs/generators/javascript-flowtyped.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/javascript.md b/docs/generators/javascript.md index 8755b0581bd8..38e933d7ae5f 100644 --- a/docs/generators/javascript.md +++ b/docs/generators/javascript.md @@ -42,7 +42,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useInheritance|use JavaScript prototype chains & delegation for inheritance| |true| |usePromises|use Promises as return values from the client API, instead of superagent callbacks| |false| |useURLSearchParams|use JS build-in UrlSearchParams, instead of deprecated npm lib 'querystring'| |true| diff --git a/docs/generators/jaxrs-cxf-cdi.md b/docs/generators/jaxrs-cxf-cdi.md index 4835693419ff..54e88fd00a53 100644 --- a/docs/generators/jaxrs-cxf-cdi.md +++ b/docs/generators/jaxrs-cxf-cdi.md @@ -77,7 +77,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|Wrap responses in CompletionStage type, allowing asynchronous computation (requires JAX-RS 2.1).| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| diff --git a/docs/generators/jaxrs-cxf-client.md b/docs/generators/jaxrs-cxf-client.md index 54ca87d4bb03..a3835496fda8 100644 --- a/docs/generators/jaxrs-cxf-client.md +++ b/docs/generators/jaxrs-cxf-client.md @@ -71,7 +71,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk.| |false| |useBeanValidation|Use BeanValidation API annotations| |false| diff --git a/docs/generators/jaxrs-cxf-extended.md b/docs/generators/jaxrs-cxf-extended.md index a1c60490c0a4..e8575723b309 100644 --- a/docs/generators/jaxrs-cxf-extended.md +++ b/docs/generators/jaxrs-cxf-extended.md @@ -80,7 +80,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportMultipleSpringServices|Support generation of Spring services from multiple specifications| |false| |testDataControlFile|JSON file to control test data generation| |null| |testDataFile|JSON file to contain generated test data| |null| diff --git a/docs/generators/jaxrs-cxf.md b/docs/generators/jaxrs-cxf.md index a450961e3907..c54b42ab061c 100644 --- a/docs/generators/jaxrs-cxf.md +++ b/docs/generators/jaxrs-cxf.md @@ -78,7 +78,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk.| |false| diff --git a/docs/generators/jaxrs-jersey.md b/docs/generators/jaxrs-jersey.md index ab46d09a13cd..b464219f0e82 100644 --- a/docs/generators/jaxrs-jersey.md +++ b/docs/generators/jaxrs-jersey.md @@ -72,7 +72,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-resteasy-eap.md b/docs/generators/jaxrs-resteasy-eap.md index 41a6403bf3cf..4bbee723e5a9 100644 --- a/docs/generators/jaxrs-resteasy-eap.md +++ b/docs/generators/jaxrs-resteasy-eap.md @@ -72,7 +72,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-resteasy.md b/docs/generators/jaxrs-resteasy.md index ded91017f160..d61e43bedc21 100644 --- a/docs/generators/jaxrs-resteasy.md +++ b/docs/generators/jaxrs-resteasy.md @@ -72,7 +72,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| |useBeanValidation|Use BeanValidation API annotations| |true| diff --git a/docs/generators/jaxrs-spec.md b/docs/generators/jaxrs-spec.md index 1c15105fb212..b5225bffd43e 100644 --- a/docs/generators/jaxrs-spec.md +++ b/docs/generators/jaxrs-spec.md @@ -78,7 +78,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/gen/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|Wrap responses in CompletionStage type, allowing asynchronous computation (requires JAX-RS 2.1).| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| |title|a title describing the application| |OpenAPI Server| diff --git a/docs/generators/jmeter.md b/docs/generators/jmeter.md index b8b108320715..7e65ce851381 100644 --- a/docs/generators/jmeter.md +++ b/docs/generators/jmeter.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/k6.md b/docs/generators/k6.md index 744b24eedb41..6c57d05e5ccc 100644 --- a/docs/generators/k6.md +++ b/docs/generators/k6.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/markdown.md b/docs/generators/markdown.md index d8fa5dbdd9bd..e4402aff390f 100644 --- a/docs/generators/markdown.md +++ b/docs/generators/markdown.md @@ -25,7 +25,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/nim.md b/docs/generators/nim.md index 174744de8f34..2c7cbaf98c8b 100644 --- a/docs/generators/nim.md +++ b/docs/generators/nim.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/nodejs-express-server.md b/docs/generators/nodejs-express-server.md index 803bac3b949f..288c953ef9bf 100644 --- a/docs/generators/nodejs-express-server.md +++ b/docs/generators/nodejs-express-server.md @@ -27,7 +27,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen on.| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/ocaml.md b/docs/generators/ocaml.md index 120638276739..ace0ed961a30 100644 --- a/docs/generators/ocaml.md +++ b/docs/generators/ocaml.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/openapi-yaml.md b/docs/generators/openapi-yaml.md index cfbf4af70a95..a60117467bd4 100644 --- a/docs/generators/openapi-yaml.md +++ b/docs/generators/openapi-yaml.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/openapi.md b/docs/generators/openapi.md index 9e5c7ff59738..c2636d3af5a5 100644 --- a/docs/generators/openapi.md +++ b/docs/generators/openapi.md @@ -26,7 +26,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/php-dt.md b/docs/generators/php-dt.md index 005e700d5e3a..18ab8967f7ab 100644 --- a/docs/generators/php-dt.md +++ b/docs/generators/php-dt.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-flight.md b/docs/generators/php-flight.md index 30b2b463726d..da33756d10f6 100644 --- a/docs/generators/php-flight.md +++ b/docs/generators/php-flight.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|camelCase| diff --git a/docs/generators/php-laravel.md b/docs/generators/php-laravel.md index 87a5280a5502..99dd2adc65bf 100644 --- a/docs/generators/php-laravel.md +++ b/docs/generators/php-laravel.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-lumen.md b/docs/generators/php-lumen.md index 84aa56bc96e1..b1855c33e3f4 100644 --- a/docs/generators/php-lumen.md +++ b/docs/generators/php-lumen.md @@ -36,7 +36,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-mezzio-ph.md b/docs/generators/php-mezzio-ph.md index c2b8013d86d9..bd408a268a8c 100644 --- a/docs/generators/php-mezzio-ph.md +++ b/docs/generators/php-mezzio-ph.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-nextgen.md b/docs/generators/php-nextgen.md index 82b35b18e4af..8691f4f2bc23 100644 --- a/docs/generators/php-nextgen.md +++ b/docs/generators/php-nextgen.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |supportStreaming|Support streaming endpoint| |false| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php-slim4.md b/docs/generators/php-slim4.md index bbf7d79b147d..e243886c016e 100644 --- a/docs/generators/php-slim4.md +++ b/docs/generators/php-slim4.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |psr7Implementation|Slim 4 provides its own PSR-7 implementation so that it works out of the box. However, you are free to replace Slim’s default PSR-7 objects with a third-party implementation. Ref: https://www.slimframework.com/docs/v4/concepts/value-objects.html|
**slim-psr7**
Slim PSR-7 Message implementation
**nyholm-psr7**
Nyholm PSR-7 Message implementation
**guzzle-psr7**
Guzzle PSR-7 Message implementation
**zend-diactoros**
Zend Diactoros PSR-7 Message implementation
|slim-psr7| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|camelCase| diff --git a/docs/generators/php-symfony.md b/docs/generators/php-symfony.md index 7ce296331456..9c865996d93c 100644 --- a/docs/generators/php-symfony.md +++ b/docs/generators/php-symfony.md @@ -42,7 +42,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/php.md b/docs/generators/php.md index 9add8db09f7b..68830fa61a66 100644 --- a/docs/generators/php.md +++ b/docs/generators/php.md @@ -38,7 +38,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |srcBasePath|The directory to serve as source root.| |null| |variableNamingConvention|naming convention of variable name, e.g. camelCase.|
**camelCase**
Use camelCase convention
**PascalCase**
Use PascalCase convention
**snake_case**
Use snake_case convention
**original**
Do not change the variable name
|snake_case| diff --git a/docs/generators/plantuml.md b/docs/generators/plantuml.md index caf04f734c31..6b92675c835f 100644 --- a/docs/generators/plantuml.md +++ b/docs/generators/plantuml.md @@ -25,7 +25,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/python-aiohttp.md b/docs/generators/python-aiohttp.md index e3fa0e9b7a5e..147e816197ce 100644 --- a/docs/generators/python-aiohttp.md +++ b/docs/generators/python-aiohttp.md @@ -34,7 +34,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen to in app.run| |8080| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testsUsePythonSrcRoot|generates test under the pythonSrcRoot folder.| |false| |useNose|use the nose test framework| |false| |usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false| diff --git a/docs/generators/python-blueplanet.md b/docs/generators/python-blueplanet.md index 09f941b48c42..667f50deed1f 100644 --- a/docs/generators/python-blueplanet.md +++ b/docs/generators/python-blueplanet.md @@ -34,7 +34,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen to in app.run| |8080| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testsUsePythonSrcRoot|generates test under the pythonSrcRoot folder.| |false| |useNose|use the nose test framework| |false| |usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false| diff --git a/docs/generators/python-fastapi.md b/docs/generators/python-fastapi.md index 8dcfdf670d4c..6f96b6ba8960 100644 --- a/docs/generators/python-fastapi.md +++ b/docs/generators/python-fastapi.md @@ -32,7 +32,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|directory for generated python source code| |src| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/python-flask.md b/docs/generators/python-flask.md index 3e74eff31f38..684d9aa7b5e6 100644 --- a/docs/generators/python-flask.md +++ b/docs/generators/python-flask.md @@ -34,7 +34,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serverPort|TCP port to listen to in app.run| |8080| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |testsUsePythonSrcRoot|generates test under the pythonSrcRoot folder.| |false| |useNose|use the nose test framework| |false| |usePythonSrcRootInImports|include pythonSrcRoot in import namespaces.| |false| diff --git a/docs/generators/ruby.md b/docs/generators/ruby.md index e6f8577dca3c..c3cd707dd0b1 100644 --- a/docs/generators/ruby.md +++ b/docs/generators/ruby.md @@ -39,7 +39,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useAutoload|Use autoload instead of require to load modules.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-akka-http-server.md b/docs/generators/scala-akka-http-server.md index 26696b81d45a..2da7ba01f804 100644 --- a/docs/generators/scala-akka-http-server.md +++ b/docs/generators/scala-akka-http-server.md @@ -38,7 +38,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useApachePekko|Use apache pekko-http instead of akka-http.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-akka.md b/docs/generators/scala-akka.md index 89296a8c4272..3526e6a010bd 100644 --- a/docs/generators/scala-akka.md +++ b/docs/generators/scala-akka.md @@ -32,7 +32,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-cask.md b/docs/generators/scala-cask.md index 9f8817ece9cc..76dcc6d8f51c 100644 --- a/docs/generators/scala-cask.md +++ b/docs/generators/scala-cask.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-gatling.md b/docs/generators/scala-gatling.md index a16121df4b0c..52af879744f7 100644 --- a/docs/generators/scala-gatling.md +++ b/docs/generators/scala-gatling.md @@ -31,7 +31,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-http4s-server.md b/docs/generators/scala-http4s-server.md index 7bcab6632c19..6f1f87b65acd 100644 --- a/docs/generators/scala-http4s-server.md +++ b/docs/generators/scala-http4s-server.md @@ -28,7 +28,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceSubfolder|name of subfolder, for example to generate code in src/scala/generated| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-http4s.md b/docs/generators/scala-http4s.md index 290777918720..1139666e60d0 100644 --- a/docs/generators/scala-http4s.md +++ b/docs/generators/scala-http4s.md @@ -31,7 +31,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-lagom-server-deprecated.md b/docs/generators/scala-lagom-server-deprecated.md index 9ff1b733e690..5c0e62eb8a44 100644 --- a/docs/generators/scala-lagom-server-deprecated.md +++ b/docs/generators/scala-lagom-server-deprecated.md @@ -31,7 +31,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-pekko.md b/docs/generators/scala-pekko.md index aab8165bb7fd..2e2545c22521 100644 --- a/docs/generators/scala-pekko.md +++ b/docs/generators/scala-pekko.md @@ -32,7 +32,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scala-play-server.md b/docs/generators/scala-play-server.md index ec0c7d5a844e..9f8824727860 100644 --- a/docs/generators/scala-play-server.md +++ b/docs/generators/scala-play-server.md @@ -34,7 +34,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportAsync|If set, wraps API return types with Futures and generates async actions.| |false| |useSwaggerUI|Add a route to /api which show your documentation in swagger-ui. Will also import needed dependencies| |true| diff --git a/docs/generators/scala-sttp.md b/docs/generators/scala-sttp.md index 39b570d9351b..0a8857baa668 100644 --- a/docs/generators/scala-sttp.md +++ b/docs/generators/scala-sttp.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |sttpClientVersion|The version of sttp client| |3.3.18| ## IMPORT MAPPING diff --git a/docs/generators/scala-sttp4-jsoniter.md b/docs/generators/scala-sttp4-jsoniter.md index e8fc4d71cdbe..b35ef71c40a7 100644 --- a/docs/generators/scala-sttp4-jsoniter.md +++ b/docs/generators/scala-sttp4-jsoniter.md @@ -33,7 +33,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |sttpClientVersion|The version of sttp client| |4.0.23| ## IMPORT MAPPING diff --git a/docs/generators/scala-sttp4.md b/docs/generators/scala-sttp4.md index ed47395f0fdc..9a246b36cec3 100644 --- a/docs/generators/scala-sttp4.md +++ b/docs/generators/scala-sttp4.md @@ -36,7 +36,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |sttpClientVersion|The version of sttp client| |4.0.0-M1| ## IMPORT MAPPING diff --git a/docs/generators/scalatra.md b/docs/generators/scalatra.md index 697884bce04a..8a3c196576bf 100644 --- a/docs/generators/scalatra.md +++ b/docs/generators/scalatra.md @@ -31,7 +31,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/scalaz.md b/docs/generators/scalaz.md index 587c85d78594..f96bbfa17862 100644 --- a/docs/generators/scalaz.md +++ b/docs/generators/scalaz.md @@ -31,7 +31,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |null| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/spring.md b/docs/generators/spring.md index dab05c8fb0d9..1cda6152be9f 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -97,7 +97,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src/main/java| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |springApiVersion|Value for 'version' attribute in @RequestMapping (for Spring 7 and above).| |null| |substituteGenericPagedModel|Detect schemas that represent paginated responses (an object with a 'content' array property and a 'page' pagination-metadata property) and replace their generated references with PagedModel<T>. By default this uses a generated type in the config package (default 'org.openapitools.configuration'), but `importMappings.PagedModel` can override it to a custom/FQCN-mapped type. The detected page schemas and the pagination metadata schema are suppressed from code generation.| |false| |testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi| diff --git a/docs/generators/swift-combine.md b/docs/generators/swift-combine.md index 9d7ab84fe78f..80fede94d007 100644 --- a/docs/generators/swift-combine.md +++ b/docs/generators/swift-combine.md @@ -29,7 +29,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |projectName|Project name in Xcode| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/generators/swift5.md b/docs/generators/swift5.md index 1041d708d549..7c3052b6e4c9 100644 --- a/docs/generators/swift5.md +++ b/docs/generators/swift5.md @@ -52,7 +52,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |responseAs|Optionally use libraries to manage response. Currently PromiseKit, RxSwift, Result, Combine, AsyncAwait are available.| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |swiftPackagePath|Set a custom source path instead of OpenAPIClient/Classes/OpenAPIs.| |null| |swiftUseApiNamespace|Flag to make all the API classes inner-class of {{projectName}}API| |null| |useBacktickEscapes|Escape reserved words using backticks (default: false)| |false| diff --git a/docs/generators/swift6.md b/docs/generators/swift6.md index cf31f3ca52d9..c3d56f6e78d8 100644 --- a/docs/generators/swift6.md +++ b/docs/generators/swift6.md @@ -54,7 +54,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |responseAs|Optionally use libraries to manage response. Currently AsyncAwait, Combine, Result, RxSwift, ObjcBlock, PromiseKit are available.| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |swiftPackagePath|Set a custom source path instead of Sources/{{projectName}}.| |null| |swiftUseApiNamespace|Flag to make all the API classes inner-class of {{projectName}}API| |null| |useBacktickEscapes|Escape reserved words using backticks (default: false)| |false| diff --git a/docs/generators/typescript-angular.md b/docs/generators/typescript-angular.md index 30eb85b5f646..1b3d1fb87e38 100644 --- a/docs/generators/typescript-angular.md +++ b/docs/generators/typescript-angular.md @@ -49,7 +49,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| diff --git a/docs/generators/typescript-aurelia.md b/docs/generators/typescript-aurelia.md index 1ac88cdca7f2..5a75ef803916 100644 --- a/docs/generators/typescript-aurelia.md +++ b/docs/generators/typescript-aurelia.md @@ -36,7 +36,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/typescript-axios.md b/docs/generators/typescript-axios.md index c192cfdbd946..5b06ed9e205d 100644 --- a/docs/generators/typescript-axios.md +++ b/docs/generators/typescript-axios.md @@ -40,7 +40,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |false| diff --git a/docs/generators/typescript-fetch.md b/docs/generators/typescript-fetch.md index bb87123aa23d..37762fabc0d9 100644 --- a/docs/generators/typescript-fetch.md +++ b/docs/generators/typescript-fetch.md @@ -41,7 +41,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |true| diff --git a/docs/generators/typescript-inversify.md b/docs/generators/typescript-inversify.md index 2c73910b95de..0060e8f01eb6 100644 --- a/docs/generators/typescript-inversify.md +++ b/docs/generators/typescript-inversify.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| |usePromise|Setting this property to use promise instead of observable inside every service.| |false| diff --git a/docs/generators/typescript-jquery.md b/docs/generators/typescript-jquery.md index 534a5360ad48..c7c9851e3dd0 100644 --- a/docs/generators/typescript-jquery.md +++ b/docs/generators/typescript-jquery.md @@ -38,7 +38,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/typescript-nestjs-server.md b/docs/generators/typescript-nestjs-server.md index d3968f0ceb4c..8017770b291d 100644 --- a/docs/generators/typescript-nestjs-server.md +++ b/docs/generators/typescript-nestjs-server.md @@ -44,7 +44,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| diff --git a/docs/generators/typescript-nestjs.md b/docs/generators/typescript-nestjs.md index 11dc7a9e7822..5c2b8d3cd002 100644 --- a/docs/generators/typescript-nestjs.md +++ b/docs/generators/typescript-nestjs.md @@ -43,7 +43,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |stringEnums|Generate string enums instead of objects for enum values.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |taggedUnions|Use discriminators to create tagged unions instead of extending interfaces.| |false| diff --git a/docs/generators/typescript-node.md b/docs/generators/typescript-node.md index 6ede8d6feb31..f7521e158abd 100644 --- a/docs/generators/typescript-node.md +++ b/docs/generators/typescript-node.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| ## IMPORT MAPPING diff --git a/docs/generators/typescript-redux-query.md b/docs/generators/typescript-redux-query.md index b1b17eb5dbc1..55e71f159430 100644 --- a/docs/generators/typescript-redux-query.md +++ b/docs/generators/typescript-redux-query.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |true| |withInterfaces|Setting this property to true will generate interfaces next to the default class implementations.| |false| diff --git a/docs/generators/typescript-rxjs.md b/docs/generators/typescript-rxjs.md index fbfa0227e844..9a7bdcf465fa 100644 --- a/docs/generators/typescript-rxjs.md +++ b/docs/generators/typescript-rxjs.md @@ -37,7 +37,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |withProgressSubscriber|Setting this property to true will generate API controller methods with support for subscribing to request progress.| |false| diff --git a/docs/generators/typescript.md b/docs/generators/typescript.md index 48a86a0771c6..57474571765c 100644 --- a/docs/generators/typescript.md +++ b/docs/generators/typescript.md @@ -42,7 +42,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsES6|Generate code that conforms to ES6.| |false| |typescriptMajorVersion|Specify the major version of TypeScript to use in the client code. Default is 5.| |5| |useErasableSyntax|Use erasable syntax for the generated code. This is a temporary feature and will be removed in the future.| |false| diff --git a/docs/generators/wsdl-schema.md b/docs/generators/wsdl-schema.md index 594c4eb0e815..4461e708ee0d 100644 --- a/docs/generators/wsdl-schema.md +++ b/docs/generators/wsdl-schema.md @@ -30,7 +30,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |soapPath|basepath of the soap services| |null| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |useSpecifiedOperationId|whether to use autogenerated operationId's (default) or those specified in openapi spec| |null| ## IMPORT MAPPING diff --git a/docs/generators/xojo-client.md b/docs/generators/xojo-client.md index 7df2374d34c3..a72a3f33bf61 100644 --- a/docs/generators/xojo-client.md +++ b/docs/generators/xojo-client.md @@ -33,7 +33,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |serializationLibrary|What serialization library to use: 'xoson' (default).| |xoson| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| |supportsAsync|Generate code that supports async operations.| |null| ## IMPORT MAPPING diff --git a/docs/generators/zapier.md b/docs/generators/zapier.md index 8137d73897bb..a36029532e26 100644 --- a/docs/generators/zapier.md +++ b/docs/generators/zapier.md @@ -25,7 +25,6 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| -|splitOperationsByContentType|Generate one operation per request/response content-type when an operation exposes several content-types with different schemas.| |false| ## IMPORT MAPPING diff --git a/docs/global-properties.md b/docs/global-properties.md index 445b7f21ce5a..359a2df0d9df 100644 --- a/docs/global-properties.md +++ b/docs/global-properties.md @@ -21,6 +21,55 @@ title: Global Properties | modelDocs | Allows the user to define if model docs will be generated. Prefer using the more robust `.openapi-generator-ignore`. | `true` or `false` | | apiTests | Allows the user to define if api tests will be generated. Prefer using the more robust `.openapi-generator-ignore`. | `true` or `false` | | modelTests | Allows the user to define if model tests will be generated. Prefer using the more robust `.openapi-generator-ignore`. | `true` or `false` | +| splitOperationsByContentType | Generates one operation per request/response content-type when an operation exposes several with different schemas | `true` or `false` | + + +## Note on splitOperationsByContentType + +An operation may declare several request or response content-types backed by *different* schemas. Only the +first one is normally kept, which leaves the others unreachable. With `splitOperationsByContentType=true` +such an operation is generated once per content-type instead — the cartesian product of the request and +response axes, deduplicated by schema — each with a typed, collision-free operation id built from the base +one: `With` for the request axis, `As` for the response axis, as in +`createReportWithXmlAsPdf`. + +The content-type declared first on each axis is the default one, consistently with the rest of the +generator. The option is opt-in and off by default, because it changes the shape of the generated API. + +Each generated operation carries `x-content-type-variant-*` extensions recording the group it was split +from, the content-type it was narrowed to on each axis and the rank of that content-type in its axis. A +generator whose language can express the whole matrix in a single construct uses them to merge the variants +back together while keeping each one's natively resolved types. `typescript-fetch` does exactly that: it +emits one method whose request type is a union discriminated by `contentType` and whose return type is +selected by overloads on `accept`. + +```ts +export type CreateReportRequest = runtime.ExclusiveUnion< + | { contentType?: 'application/json'; report?: Report; } + | { contentType: 'application/xml'; reportXml?: ReportXml; } +>; + +async createReport(requestParameters: CreateReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; +async createReport(requestParameters: CreateReportRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; +``` + +`ExclusiveUnion` makes the members mutually exclusive, by declaring on each of them the keys it does not +have as `never`. Without it nothing stops a caller from handing an XML body to the JSON member and having it +silently sent as JSON: excess property checking, which would normally reject the surplus property, treats a +key present in *any* member of a union as known, so it never fires here — for an object literal no more than +for a variable. What rejects most shapes is unrelated: weak type detection when every property of a member +is optional, a missing required property otherwise. A member with a required parameter and an optional body +has neither. The helper is emitted into `runtime.ts` only when this option is on. + +A form or multipart content-type is merged like any other: its parameters stay individual rather than +gathered in a single body, so the union member carries them as they are and the body is assembled inside +that content-type's branch of the switch. `Content-Type` is set in each branch rather than once up front, +because a multipart body must not set it at all — `fetch` adds it with the boundary it generates. + +One case is left split rather than merged, with a warning: every operation when `useSingleRequestParameter` +is off, since the parameters are then spread over the signature and there is no request object to carry the +discriminant. The separate, individually typed methods the split produced are then generated as they are, +which is what a statically-typed generator emits anyway. ## Note on Global Property declaration diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java index 4a7f98c5b02d..81e7c759d730 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java @@ -33,6 +33,7 @@ import org.openapitools.codegen.model.WebhooksMap; import java.io.File; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -134,7 +135,9 @@ public interface CodegenConfig { * Divides an operation into one operation per content-type when it exposes several request/response * content-types with different schemas (opt-in, see {@code splitOperationsByContentType}). Each * returned operation is self-contained and re-enters {@link #fromOperation}. When the option is off or - * no division applies, the operation is returned unchanged (as a singleton). + * no division applies, the operation is returned unchanged (as a singleton). {@code DefaultCodegen} + * implements the division; the default here keeps the operation whole so that an implementation not + * deriving from {@code DefaultCodegen} keeps compiling and simply opts out of the feature. * * @param openAPI the OpenAPI document * @param path the resource path @@ -142,7 +145,9 @@ public interface CodegenConfig { * @param operation the operation to (maybe) divide * @return the operations to generate for {@code operation} (the operation itself when not divided) */ - List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation); + default List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { + return Collections.singletonList(operation); + } List fromSecurity(Map schemas); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index bdc494e5a10b..37cc5f198497 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -151,7 +151,22 @@ public class CodegenConstants { public static final String PREPEND_FORM_OR_BODY_PARAMETERS_DESC = "Add form or body parameters to the beginning of the parameter list."; public static final String SPLIT_OPERATIONS_BY_CONTENT_TYPE = "splitOperationsByContentType"; - public static final String SPLIT_OPERATIONS_BY_CONTENT_TYPE_DESC = "Generate one operation per request/response content-type when an operation exposes several content-types with different schemas."; + + /** + * Extensions set on every operation produced by {@code splitOperationsByContentType}, describing where + * the variant sits in the content-type matrix so that a generator can merge the variants back into a + * single construct instead of emitting one method per combination. + *

+ * The {@code *-index} ones carry the 0-based rank of the variant's media-type in its axis, in the order + * the spec declares them, so a consumer never has to rely on the order operations happen to reach it in: + * rank 0 is that axis's default content-type, and the variant ranked 0 on both axes is the one a caller + * gets without asking. An axis that was not split has no media-type and ranks 0. + */ + public static final String X_CONTENT_TYPE_VARIANT_GROUP = "x-content-type-variant-group"; + public static final String X_CONTENT_TYPE_VARIANT_REQUEST = "x-content-type-variant-request"; + public static final String X_CONTENT_TYPE_VARIANT_RESPONSE = "x-content-type-variant-response"; + public static final String X_CONTENT_TYPE_VARIANT_REQUEST_INDEX = "x-content-type-variant-request-index"; + public static final String X_CONTENT_TYPE_VARIANT_RESPONSE_INDEX = "x-content-type-variant-response-index"; public static final String USE_DATETIME_OFFSET = "useDateTimeOffset"; public static final String USE_DATETIME_OFFSET_DESC = "Use DateTimeOffset to model date-time properties"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 786962d3924f..3407ef094039 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -419,7 +419,11 @@ public void processOpts() { convertPropertyToBooleanAndWriteBack(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, this::setPrependFormOrBodyParameters); convertPropertyToBooleanAndWriteBack(CodegenConstants.ENSURE_UNIQUE_PARAMS, this::setEnsureUniqueParams); convertPropertyToBooleanAndWriteBack(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, this::setAllowUnicodeIdentifiers); - convertPropertyToBooleanAndWriteBack(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, this::setSplitOperationsByContentType); + // splitOperationsByContentType is a global option rather than a generator one: the behaviour is + // language-neutral and applies to every generator alike, so it is read from the global properties + // (--global-property) and is deliberately absent from cliOptions. + setSplitOperationsByContentType(Boolean.parseBoolean( + GlobalSettings.getProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false"))); convertPropertyToStringAndWriteBack(CodegenConstants.API_NAME_PREFIX, this::setApiNamePrefix); convertPropertyToStringAndWriteBack(CodegenConstants.API_NAME_SUFFIX, this::setApiNameSuffix); convertPropertyToStringAndWriteBack(CodegenConstants.MODEL_NAME_PREFIX, this::setModelNamePrefix); @@ -1073,6 +1077,10 @@ public void setSplitOperationsByContentType(boolean splitOperationsByContentType * {@code fromOperation} and is typed natively by the target generator. This keeps the feature * language-neutral: no per-language type re-derivation here. Returns the operation as a singleton when * the option is off or no division applies. + *

+ * Every variant carries the {@code x-content-type-variant-*} extensions describing its place in the + * matrix, so a generator able to express the whole matrix in a single construct — TypeScript overloads, + * for instance — can merge the variants back together while keeping each one's natively resolved types. */ @Override public List divideOperationsByContentType(OpenAPI openAPI, String path, String httpMethod, Operation operation) { @@ -1080,110 +1088,177 @@ public List divideOperationsByContentType(OpenAPI openAPI, String pat return Collections.singletonList(operation); } RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); - List requestAxis = axisOf(requestBody == null ? null : requestBody.getContent()); + List requestAxis = axisOf(requestBody == null ? null : requestBody.getContent()); // Only the response the generator derives the return type from (the method response) is split, so the // variants' return types and Accept headers stay consistent (see findMethodResponse). String methodResponseCode = operation.getResponses() == null ? null : findMethodResponseCode(operation.getResponses()); ApiResponse methodResponse = methodResponseCode == null ? null : ModelUtils.getReferencedApiResponse(openAPI, operation.getResponses().get(methodResponseCode)); - List responseAxis = axisOf(methodResponse == null ? null : methodResponse.getContent()); + List responseAxis = axisOf(methodResponse == null ? null : methodResponse.getContent()); - boolean requestSplit = requestAxis.size() > 1; - boolean responseSplit = responseAxis.size() > 1; - if (!requestSplit && !responseSplit) { + if (requestAxis.size() == 1 && responseAxis.size() == 1) { return Collections.singletonList(operation); // single content-type on both axes: nothing to divide } + // Both axes are in declaration order, so rank 0 is the default content-type, consistently with the + // rest of the generator: addConsumesInfo keeps that order and templates read consumes.0. String baseId = getOrGenerateOperationId(operation, path, httpMethod); List variants = new ArrayList<>(requestAxis.size() * responseAxis.size()); - for (String requestMediaType : requestAxis) { - for (String responseMediaType : responseAxis) { - variants.add(buildOperationVariant(openAPI, operation, baseId, - requestSplit ? requestMediaType : null, - responseSplit ? responseMediaType : null, - methodResponseCode, methodResponse)); + for (Axis request : requestAxis) { + for (Axis response : responseAxis) { + Operation variant = buildOperationVariant(openAPI, operation, baseId, request, response, + methodResponseCode, methodResponse); + tagContentTypeVariant(variant, baseId, request, response); + variants.add(variant); } } return variants; } /** - * The media-types of {@code content} deduplicated by resolved schema (so two media-types mapping to - * the same schema collapse), JSON-first for determinism. Returns a singleton {@code [null]} when there - * are fewer than two distinct schemas, meaning "do not split this axis". + * One position on a content-type axis. {@link Axis#NOT_SPLIT} is the single position of an axis that + * stays as it is; the others carry the media-type the variant is narrowed to, the token its operationId + * is built from, and the rank the spec declares that media-type at. */ - private List axisOf(Content content) { + private static final class Axis { + private static final Axis NOT_SPLIT = new Axis(null, null, 0); + + private final String mediaType; + private final String token; + private final int rank; + + private Axis(String mediaType, String token, int rank) { + this.mediaType = mediaType; + this.token = token; + this.rank = rank; + } + } + + /** + * The media-types of {@code content} deduplicated by resolved schema (two media-types sharing a schema + * collapse into the first one declared), kept in declaration order: that is the order the rest of the + * generator already treats as authoritative, so rank 0 is the content-type a caller gets by default. + * Returns a singleton {@link Axis#NOT_SPLIT} when fewer than two distinct schemas remain. + */ + private List axisOf(Content content) { if (content == null || content.size() < 2) { - return Collections.singletonList(null); + return Collections.singletonList(Axis.NOT_SPLIT); } - List kept = new ArrayList<>(); - Set seenSchemas = new LinkedHashSet<>(); + List mediaTypes = new ArrayList<>(); + Set seenSchemas = new HashSet<>(); for (Map.Entry entry : content.entrySet()) { - String key = schemaKey(entry.getValue() == null ? null : entry.getValue().getSchema()); - if (seenSchemas.add(key)) { - kept.add(entry.getKey()); + if (seenSchemas.add(schemaKey(entry.getValue() == null ? null : entry.getValue().getSchema()))) { + mediaTypes.add(entry.getKey()); } } - if (kept.size() < 2) { - return Collections.singletonList(null); + if (mediaTypes.size() < 2) { + return Collections.singletonList(Axis.NOT_SPLIT); } - String preferred = kept.stream().filter(mt -> isJsonMimeType(mt)).findFirst().orElse(kept.get(0)); - List ordered = new ArrayList<>(kept.size()); - ordered.add(preferred); - for (String mediaType : kept) { - if (!mediaType.equals(preferred)) { - ordered.add(mediaType); - } + // the subtype alone identifies most media-types, but not all: text/csv and application/csv would + // both be Csv and give two variants the same operationId, so those fall back to the whole type + Map bySubtype = mediaTypes.stream() + .collect(Collectors.groupingBy(DefaultCodegen::subtypeToken, Collectors.counting())); + List axis = new ArrayList<>(mediaTypes.size()); + for (int rank = 0; rank < mediaTypes.size(); rank++) { + String mediaType = mediaTypes.get(rank); + String subtype = subtypeToken(mediaType); + axis.add(new Axis(mediaType, bySubtype.get(subtype) > 1 ? sanitizeToken(mediaType) : subtype, rank)); + } + return axis; + } + + /** + * Records where a variant sits in the content-type matrix so that a generator able to express the whole + * matrix in a single construct can merge the variants back together: the group they belong to, the + * media-type they were narrowed to on each axis (absent when that axis was not split) and its rank in + * that axis. See {@link CodegenConstants#X_CONTENT_TYPE_VARIANT_REQUEST_INDEX}. + */ + private static void tagContentTypeVariant(Operation variant, String group, Axis request, Axis response) { + Map extensions = variant.getExtensions(); + extensions.put(CodegenConstants.X_CONTENT_TYPE_VARIANT_GROUP, group); + if (request.mediaType != null) { + extensions.put(CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST, request.mediaType); + } + if (response.mediaType != null) { + extensions.put(CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE, response.mediaType); } - return ordered; + // the rank travels with the variant: the operations are reordered before they reach a generator, + // so their position in the list is no longer the order declared in the spec + extensions.put(CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST_INDEX, request.rank); + extensions.put(CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE_INDEX, response.rank); } /** * Builds one operation variant narrowed to a single request and/or response media-type (a {@code null} * media-type leaves that axis untouched), with a typed, collision-free operationId. */ - private Operation buildOperationVariant(OpenAPI openAPI, Operation original, String baseId, String requestMediaType, - String responseMediaType, String targetResponseCode, ApiResponse targetResponse) { - boolean openapi31 = specVersionGreaterThanOrEqualTo310(openAPI); - Operation variant = ModelUtils.cloneOperation(original, openapi31); - // generators (e.g. SpringCodegen) read the extensions map without null-guards - if (variant.getExtensions() == null) { - variant.setExtensions(new LinkedHashMap<>()); - } + private Operation buildOperationVariant(OpenAPI openAPI, Operation original, String baseId, + Axis request, Axis response, + String targetResponseCode, ApiResponse targetResponse) { + Operation variant = shallowCopyOperation(original); // typed, collision-free operationId: request -> "With", response -> "As" StringBuilder operationId = new StringBuilder(baseId); - if (requestMediaType != null) { - operationId.append("With").append(camelize(subtypeToken(requestMediaType))); + if (request.mediaType != null) { + operationId.append("With").append(camelize(request.token)); } - if (responseMediaType != null) { - operationId.append("As").append(camelize(subtypeToken(responseMediaType))); + if (response.mediaType != null) { + operationId.append("As").append(camelize(response.token)); } variant.setOperationId(operationId.toString()); - if (requestMediaType != null) { + if (request.mediaType != null) { RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, original.getRequestBody()); - variant.setRequestBody(narrowRequestBody(requestBody, requestMediaType, openapi31)); + variant.setRequestBody(narrowRequestBody(requestBody, request.mediaType)); } - if (responseMediaType != null) { - variant.setResponses(narrowResponses(original.getResponses(), targetResponseCode, targetResponse, responseMediaType, openapi31)); + if (response.mediaType != null) { + variant.setResponses(narrowResponses(original.getResponses(), targetResponseCode, targetResponse, response.mediaType)); } return variant; } - private RequestBody narrowRequestBody(RequestBody source, String mediaType, boolean openapi31) { - RequestBody copy = ModelUtils.cloneRequestBody(source, openapi31); + /** + * Copies an {@link Operation} one level deep: the copy gets its own parameter and extension lists, + * which the split writes to, and shares everything below — schemas above all, which it only reads. + * A deep copy would have to round-trip through the mapper, which drops any schema whose type is not + * a standard OpenAPI < 3.1 one. + */ + private Operation shallowCopyOperation(Operation source) { + Operation copy = new Operation(); + copy.setTags(source.getTags()); + copy.setSummary(source.getSummary()); + copy.setDescription(source.getDescription()); + copy.setExternalDocs(source.getExternalDocs()); + copy.setOperationId(source.getOperationId()); + copy.setParameters(source.getParameters() == null ? null : new ArrayList<>(source.getParameters())); + copy.setRequestBody(source.getRequestBody()); + copy.setResponses(source.getResponses()); + copy.setCallbacks(source.getCallbacks()); + copy.setDeprecated(source.getDeprecated()); + copy.setSecurity(source.getSecurity() == null ? null : new ArrayList<>(source.getSecurity())); + copy.setServers(source.getServers()); + // a non-null extensions map: the split writes the variant's place in the matrix into it, and + // generators (SpringCodegen for one) read it without null-guards + copy.setExtensions(source.getExtensions() == null ? new LinkedHashMap<>() : new LinkedHashMap<>(source.getExtensions())); + return copy; + } + + private RequestBody narrowRequestBody(RequestBody source, String mediaType) { + RequestBody copy = new RequestBody(); + copy.setDescription(source.getDescription()); + copy.setRequired(source.getRequired()); + copy.setExtensions(source.getExtensions()); copy.setContent(singleContent(source.getContent(), mediaType)); return copy; } - private ApiResponses narrowResponses(ApiResponses responses, String targetCode, ApiResponse targetResponse, String mediaType, boolean openapi31) { + private ApiResponses narrowResponses(ApiResponses responses, String targetCode, ApiResponse targetResponse, String mediaType) { ApiResponses copy = new ApiResponses(); copy.setExtensions(responses.getExtensions()); for (Map.Entry entry : responses.entrySet()) { if (entry.getKey().equals(targetCode)) { - copy.addApiResponse(entry.getKey(), narrowApiResponse(targetResponse, mediaType, openapi31)); + copy.addApiResponse(entry.getKey(), narrowApiResponse(targetResponse, mediaType)); } else { copy.addApiResponse(entry.getKey(), entry.getValue()); } @@ -1191,8 +1266,12 @@ private ApiResponses narrowResponses(ApiResponses responses, String targetCode, return copy; } - private ApiResponse narrowApiResponse(ApiResponse source, String mediaType, boolean openapi31) { - ApiResponse copy = ModelUtils.cloneApiResponse(source, openapi31); + private ApiResponse narrowApiResponse(ApiResponse source, String mediaType) { + ApiResponse copy = new ApiResponse(); + copy.setDescription(source.getDescription()); + copy.setHeaders(source.getHeaders()); + copy.setLinks(source.getLinks()); + copy.setExtensions(source.getExtensions()); copy.setContent(singleContent(source.getContent(), mediaType)); return copy; } @@ -1217,9 +1296,22 @@ private static String schemaKey(Schema schema) { if (schema.getItems() != null) { key.append("|items=").append(schemaKey(schema.getItems())); } + // the property names too: without them two different inline object schemas share a key, and the + // media-type of the second one is dropped from the generated client with nothing said + if (schema.getProperties() != null) { + key.append("|props=").append(new TreeSet<>(schema.getProperties().keySet())); + } + if (schema.getAdditionalProperties() instanceof Schema) { + key.append("|addProps=").append(schemaKey((Schema) schema.getAdditionalProperties())); + } return key.toString(); } + /** Whole media-type reduced to an identifier, e.g. {@code text_csv} from {@code text/csv}. */ + private static String sanitizeToken(String mediaType) { + return mediaType.replaceAll("\\+.*$", "").replaceAll("[^a-zA-Z0-9]+", "_"); + } + /** Token derived from a media-type subtype, e.g. {@code Directlog} from {@code application/directlog}. */ private static String subtypeToken(String mediaType) { String subtype = mediaType.substring(mediaType.indexOf('/') + 1); @@ -2002,10 +2094,6 @@ public DefaultCodegen() { // option to change the order of form/body parameter cliOptions.add(CliOption.newBoolean(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS_DESC).defaultValue(Boolean.FALSE.toString())); - // option to split operations that expose several request/response content-types with different schemas - cliOptions.add(CliOption.newBoolean(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, - CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE_DESC).defaultValue(Boolean.FALSE.toString())); - // option to change how we process + set the data in the discriminator mapping CliOption legacyDiscriminatorBehaviorOpt = CliOption.newBoolean(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR_DESC).defaultValue(Boolean.TRUE.toString()); Map legacyDiscriminatorBehaviorOpts = new HashMap<>(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java index ce27455eabd3..278a1387f5ae 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java @@ -36,19 +36,25 @@ import org.openapitools.codegen.model.OperationsMap; import org.openapitools.codegen.templating.mustache.IndentedLambda; import org.openapitools.codegen.utils.ModelUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; +import java.util.function.BiConsumer; import java.util.stream.Collectors; import static java.util.Objects.nonNull; import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; +import static org.openapitools.codegen.utils.OnceLogger.once; import static org.openapitools.codegen.utils.StringUtils.*; /** *

Mustache templates are located in {@code src/main/resources/typescript-fetch/}. */ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodegen { + private static final Logger LOGGER = LoggerFactory.getLogger(TypeScriptFetchClientCodegen.class); + public static final String NPM_REPOSITORY = "npmRepository"; public static final String WITH_INTERFACES = "withInterfaces"; public static final String USE_SINGLE_REQUEST_PARAMETER = "useSingleRequestParameter"; @@ -246,6 +252,9 @@ public boolean isUniqueIdAccordingToNameSuffix(String name) { @Override public void processOpts() { super.processOpts(); + // runtime.ts only carries the ExclusiveUnion helper when the option that needs it is on, so an + // ordinary client is byte-for-byte what it was + additionalProperties.put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, splitOperationsByContentType); additionalProperties.put("isOriginalModelPropertyNaming", getModelPropertyNaming() == CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.original); additionalProperties.put("modelPropertyNaming", getModelPropertyNaming().name()); @@ -373,6 +382,9 @@ protected ImmutableMap.Builder addMustacheLambdas() { ImmutableMap.Builder lambdas = super.addMustacheLambdas(); lambdas.put("indented_star_1", new IndentedLambda(1, " ", "* ", false, false)); lambdas.put("indented_star_4", new IndentedLambda(5, " ", "* ", false, false)); + // the shared indented_N lambdas indent blank lines too, leaving trailing whitespace; these skip + // them, so a flush-left partial can be shared between call sites at different depths + lambdas.put("indented_8_skip_blank", new IndentedLambda(8, " ", false, true)); return lambdas; } @@ -746,6 +758,11 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap operations, L } this.addOperationObjectResponseInformation(operations); this.addOperationPrefixParameterInterfacesInformation(operations); + // last: the merge drops the non-default variants from the list while the merged operation keeps + // referencing their parameters and return types. Every pass above has to have seen them by then - + // updateOperationParameterForEnum, for one, is what prefixes an enum parameter's type name with the + // operation's, and a variant it never visited would be left referencing a type nobody declares. + this.mergeContentTypeVariants(operations); return operations; } @@ -935,16 +952,260 @@ private boolean processCodegenProperty(ExtendedCodegenProperty var, String paren private void escapeOperationIds(OperationsMap operations) { for (CodegenOperation _op : operations.getOperations().getOperation()) { ExtendedCodegenOperation op = (ExtendedCodegenOperation) _op; - String param = op.operationIdCamelCase + "Request"; - if (op.imports.contains(param)) { + if (op.imports.contains(op.operationIdCamelCase + "Request")) { // we import a model with the same name as the generated operation, escape it - op.operationIdCamelCase += "Operation"; - op.operationIdLowerCase += "operation"; - op.operationIdSnakeCase += "_operation"; + escapeOperationId(op); + } + } + } + + private static void escapeOperationId(CodegenOperation op) { + op.operationIdCamelCase += "Operation"; + op.operationIdLowerCase += "operation"; + op.operationIdSnakeCase += "_operation"; + } + + /** + * Merges the operations produced by the global {@code splitOperationsByContentType} option back into a + * single method per original operation. + *

+ * The split emits one operation per (request content-type, response content-type) pair so that every + * variant is typed natively by the generator. Statically-typed languages need those separate methods, + * but TypeScript can express the whole matrix at once: the variants are collapsed into one method whose + * request type is a union discriminated by {@code contentType}, and whose return type is selected by + * overloads on {@code accept}. Each variant keeps its own natively resolved body and return types, which + * is exactly what the split computed. + *

+ * The one shape the merged form cannot express is {@code useSingleRequestParameter} off: with the + * parameters spread over the signature there is no request object to carry the discriminant. Those + * operations are left split, with a warning. + */ + /** Media-type the merged operation sends as Accept when the caller does not pick one. */ + private static final String X_CONTENT_TYPE_DEFAULT_RESPONSE = "x-content-type-default-response"; + + private void mergeContentTypeVariants(OperationsMap operations) { + if (!splitOperationsByContentType) { + return; + } + List allOperations = operations.getOperations().getOperation(); + if (!this.getUseSingleRequestParameter()) { + // the merged form carries the discriminant on the request object; with the parameters spread + // over the signature there is nothing to discriminate on + if (allOperations.stream().anyMatch(op -> op.vendorExtensions.containsKey(CodegenConstants.X_CONTENT_TYPE_VARIANT_GROUP))) { + once(LOGGER).warn("`{}` is off: content-type variants are generated as separate methods rather " + + "than merged into one.", USE_SINGLE_REQUEST_PARAMETER); + } + return; + } + + // LinkedHashMap only to keep the groups themselves in a stable order; within a group the axis order + // comes from the rank each variant carries, not from its position here - see variantsByRank. + Map> groups = new LinkedHashMap<>(); + for (CodegenOperation op : allOperations) { + Object group = op.vendorExtensions.get(CodegenConstants.X_CONTENT_TYPE_VARIANT_GROUP); + if (group != null) { + groups.computeIfAbsent(group + " " + op.httpMethod + " " + op.path, k -> new ArrayList<>()).add(op); + } + } + + // identity-based: CodegenOperation.hashCode() walks the whole operation, and two variants of the + // same operation are very nearly equal + Set superseded = Collections.newSetFromMap(new IdentityHashMap<>()); + for (List variants : groups.values()) { + if (variants.size() < 2) { + continue; + } + List requestVariants = requestVariantsOf(variants); + List responseVariants = responseVariantsOf(variants); + + // the surviving operation is the one a caller gets without asking: rank 0 on both axes + CodegenOperation base = variants.stream() + .filter(TypeScriptFetchClientCodegen::isDefaultVariant) + .findFirst() + .orElse(variants.get(0)); + + renameToGroupOperationId(base, variants); + ExtendedCodegenOperation merged = (ExtendedCodegenOperation) base; + merged.contentTypeMerged = true; + merged.contentTypeRequestVariants = requestVariants; + merged.contentTypeResponseVariants = responseVariants; + merged.contentTypeMergedEnumParams = enumParamsOf(variants); + merged.hasContentTypeRequestVariants = requestVariants.size() > 1; + merged.hasContentTypeResponseVariants = responseVariants.size() > 1; + base.vendorExtensions.put(X_CONTENT_TYPE_DEFAULT_RESPONSE, + responseVariants.get(0).mediaType); + if (responseVariants.size() > 1) { + // the same variants, but ordered for an if / else if / else chain: the default content-type + // is the fallback, so it comes last there rather than first. Only meaningful beyond one + // variant - a single one would be both the chain's first and last branch. + List dispatch = new ArrayList<>(responseVariants); + Collections.rotate(dispatch, -1); + merged.contentTypeResponseDispatch = dispatch; + } + + variants.stream().filter(op -> op != base).forEach(superseded::add); + } + + // identity-based membership, so a variant is dropped without being compared field by field + allOperations.removeAll(superseded); + } + + /** + * One entry per distinct request content-type, in declaration order, carrying the body that content-type + * expects as the generator resolved it. A single-element list means the request axis was not split. + */ + private List requestVariantsOf(List variants) { + return variantsByRank(variants, CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST, + CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST_INDEX, (entry, variant) -> { + entry.allParams = variant.allParams; + entry.bodyParam = variant.bodyParam; + // a form or multipart variant carries its body in individual parameters rather than in a + // body parameter: the template assembles it per content-type, from these + entry.hasFormParams = variant.getHasFormParams(); + entry.formParams = variant.formParams; + entry.consumes = variant.consumes; + }); + } + + /** + * One entry per distinct response content-type, in declaration order, carrying the return type the + * generator resolved for it and the flags {@code apisResponseVariantValue.mustache} needs to pick a + * deserialiser. A single-element list means the response axis was not split. + */ + private List responseVariantsOf(List variants) { + return variantsByRank(variants, CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE, + CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE_INDEX, (entry, variant) -> { + entry.returnType = variant.returnType; + entry.returnBaseType = variant.returnBaseType; + entry.isResponseFile = variant.isResponseFile; + entry.returnTypeIsPrimitive = variant.returnTypeIsPrimitive; + entry.returnSimpleType = variant.returnSimpleType; + entry.isArray = variant.isArray; + entry.isMap = variant.isMap; + entry.uniqueItems = variant.uniqueItems; + }); + } + + /** + * Groups the variants by their rank on one axis, one entry per media-type, ordered by the rank the split + * recorded — the order the spec declares the content-types in. The rank is read from the variants rather + * than from their position in the list, which is not the split's: operations are reordered on their way + * to the generator. + */ + private List variantsByRank(List variants, String axisExtension, + String indexExtension, + BiConsumer describe) { + Map byRank = new TreeMap<>(); + for (CodegenOperation variant : variants) { + Integer rank = (Integer) variant.vendorExtensions.get(indexExtension); + byRank.computeIfAbsent(rank, key -> { + ContentTypeVariant entry = new ContentTypeVariant(); + // an axis left unsplit has no media-type: every variant then represents the same, single one + entry.mediaType = (String) variant.vendorExtensions.get(axisExtension); + entry.isDefault = key == 0; + describe.accept(entry, variant); + return entry; + }); + } + return new ArrayList<>(byRank.values()); + } + + /** + * One content-type of a merged operation, on one axis. Read by the templates through their own field + * names, so a mistyped one fails to compile rather than rendering as nothing. + */ + public static class ContentTypeVariant { + public String mediaType; + public boolean isDefault; + + // request axis + public List allParams, formParams; + public CodegenParameter bodyParam; + public boolean hasFormParams; + public List> consumes; + + // response axis + public boolean isResponseFile, returnTypeIsPrimitive, returnSimpleType, isArray, isMap, uniqueItems; + public String returnType, returnBaseType; + } + + /** + * Renames the enum types of every variant's parameters after the merged operation rather than after the + * variant they came from. + *

+ * {@code updateOperationParameterForEnum} prefixes an enum parameter's type with its operation's name, so + * that two operations sharing a parameter name do not declare the same type twice. It ran before the + * merge, when each variant still had its own name — but the enum is declared once, under the merged + * operation's name, and the request union references every variant's parameters. + */ + private void reprefixEnumParameters(List variants, String mergedIdCamelCase) { + for (CodegenOperation variant : variants) { + for (CodegenParameter param : variant.allParams) { + if (Boolean.TRUE.equals(param.isEnum) && param.datatypeWithEnum != null) { + param.datatypeWithEnum = param.datatypeWithEnum.replace( + variant.operationIdCamelCase + param.enumName, mergedIdCamelCase + param.enumName); + } } } } + /** + * Every enum parameter of every variant, deduplicated by enum type name, in variant order. The request + * union references them all, but only the surviving variant's parameters remain reachable through + * allParams — the enum declarations are emitted from this list instead. Two variants declaring the same + * enum name (a query parameter they share, most commonly) collapse into one declaration. + */ + private static List enumParamsOf(List variants) { + Map byEnumName = new LinkedHashMap<>(); + for (CodegenOperation variant : variants) { + for (CodegenParameter param : variant.allParams) { + if (Boolean.TRUE.equals(param.isEnum) && param.enumName != null) { + byEnumName.putIfAbsent(param.enumName, param); + } + } + } + return new ArrayList<>(byEnumName.values()); + } + + /** The variant a caller gets without asking: rank 0 on both axes. */ + private static boolean isDefaultVariant(CodegenOperation op) { + return Integer.valueOf(0).equals(op.vendorExtensions.get(CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST_INDEX)) + && Integer.valueOf(0).equals(op.vendorExtensions.get(CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE_INDEX)); + } + + /** + * Gives a merged operation back the name of the operation it was split from, and moves the variants' enum + * types onto that name. + *

+ * The two belong together: reprefixEnumParameters reads each variant's current name, so it has to run + * before this one is renamed. Splitting them across two calls made that ordering invisible, and easy to + * get backwards. + */ + private void renameToGroupOperationId(CodegenOperation operation, List variants) { + String group = (String) operation.vendorExtensions.get(CodegenConstants.X_CONTENT_TYPE_VARIANT_GROUP); + String operationId = toOperationId(group); + String camelCase = camelize(operationId); + // escapeOperationIds ran on the variants' suffixed names, so it could not see the merged name: + // its escape is replayed here. The merged method references every variant's types, hence the + // union of their imports. + String requestName = camelCase + "Request"; + boolean collides = variants.stream().anyMatch(variant -> variant.imports.contains(requestName)); + + // before the rename: reprefixEnumParameters matches on each variant's current name, and the merged + // operation is one of the variants + reprefixEnumParameters(variants, collides ? camelCase + "Operation" : camelCase); + + operation.operationIdOriginal = group; + operation.operationId = operationId; + operation.nickname = operationId; + operation.operationIdCamelCase = camelCase; + operation.operationIdLowerCase = operationId.toLowerCase(Locale.ROOT); + operation.operationIdSnakeCase = underscore(operationId); + if (collides) { + escapeOperationId(operation); + } + } + private void addOperationModelImportInformation(OperationsMap operations) { // This method will add extra information to the operations.imports array. // The api template uses this information to import all the required @@ -1445,6 +1706,23 @@ public class ExtendedCodegenOperation extends CodegenOperation { boolean hasReturnPassthroughVoid, returnTypeSupportsEntities, returnTypeIsModel, returnTypeIsArray; String returnTypeAlternate, returnBaseTypeAlternate, returnPassthrough; + /** + * Set by {@link TypeScriptFetchClientCodegen#mergeContentTypeVariants} on an operation merged back + * from its content-type variants. Fields rather than vendor extensions: a mistyped `x-` key renders + * as nothing at all in a template, and {@link CodegenOperation#hashCode()} walks the extensions map, + * which these lists have no business being dragged through. + */ + public boolean contentTypeMerged, hasContentTypeRequestVariants, hasContentTypeResponseVariants; + public List contentTypeRequestVariants, contentTypeResponseVariants; + /** The response variants ordered for an if / else if / else chain: the default one comes last. */ + public List contentTypeResponseDispatch; + /** + * Every enum parameter the merged request union references, across all the variants, deduplicated + * by the name of the type it declares. The enum declaration block walks this rather than allParams, + * which only holds the surviving variant's parameters. + */ + public List contentTypeMergedEnumParams; + public ExtendedCodegenOperation(CodegenOperation o) { super(); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 41fe5ed14ade..88346d9046f7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -20,8 +20,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.AnnotationsUtils; -import io.swagger.v3.core.util.Json; -import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -2317,45 +2315,6 @@ public static Schema cloneSchema(Schema schema, boolean openapi31) { } } - /** - * Deep-clones an {@link Operation} through the swagger object mapper (like {@link #cloneSchema}). - * - * @param source the operation to clone - * @param openapi31 whether the document is OpenAPI 3.1 (selects the matching mapper so embedded - * schemas are serialized with the right dialect) - * @return a deep clone of {@code source} - */ - public static Operation cloneOperation(Operation source, boolean openapi31) { - return cloneViaMapper(source, Operation.class, openapi31); - } - - /** - * Deep-clones a {@link RequestBody} through the swagger object mapper. - * - * @param source the request body to clone - * @param openapi31 whether the document is OpenAPI 3.1 - * @return a deep clone of {@code source} - */ - public static RequestBody cloneRequestBody(RequestBody source, boolean openapi31) { - return cloneViaMapper(source, RequestBody.class, openapi31); - } - - /** - * Deep-clones an {@link ApiResponse} through the swagger object mapper. - * - * @param source the response to clone - * @param openapi31 whether the document is OpenAPI 3.1 - * @return a deep clone of {@code source} - */ - public static ApiResponse cloneApiResponse(ApiResponse source, boolean openapi31) { - return cloneViaMapper(source, ApiResponse.class, openapi31); - } - - private static T cloneViaMapper(T source, Class type, boolean openapi31) { - ObjectMapper mapper = openapi31 ? Json31.mapper() : Json.mapper(); - return mapper.convertValue(source, type); - } - /** * Simplifies the schema by removing the oneOfAnyOf if the oneOfAnyOf only contains a single non-null sub-schema * diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache index 82f466757b86..cc714f777a36 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache @@ -22,6 +22,19 @@ import { {{#operations}} {{#operation}} +{{#contentTypeMerged}} +{{! the operation accepts several request content-types with different schemas: one union member per + content-type, discriminated by `contentType`, whose value selects the body's type }} +{{! runtime.ExclusiveUnion makes the members mutually exclusive: without it a value carrying another + member's body satisfies this one, and the body goes out under the wrong content-type }} +export type {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request = {{#hasContentTypeRequestVariants}}runtime.ExclusiveUnion<{{/hasContentTypeRequestVariants}} +{{#contentTypeRequestVariants}} + | { {{#hasContentTypeRequestVariants}}contentType{{#isDefault}}?{{/isDefault}}: '{{mediaType}}'; {{/hasContentTypeRequestVariants}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{#hasReadOnly}}Omit<{{{dataType}}}, {{#readOnlyVars}}'{{baseName}}'{{^-last}}|{{/-last}}{{/readOnlyVars}}>{{/hasReadOnly}}{{^hasReadOnly}}{{{dataType}}}{{/hasReadOnly}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}; {{/allParams}}} +{{/contentTypeRequestVariants}} +{{#hasContentTypeRequestVariants}}>{{/hasContentTypeRequestVariants}}; + +{{/contentTypeMerged}} +{{^contentTypeMerged}} {{#allParams.0}} export interface {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request { {{#allParams}} @@ -30,6 +43,7 @@ export interface {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterIn } {{/allParams.0}} +{{/contentTypeMerged}} {{/operation}} {{/operations}} {{#withInterfaces}} @@ -54,7 +68,7 @@ export interface {{classname}}Interface { * @throws {RequiredError} * @memberof {{classname}}Interface */ - {{nickname}}RequestOpts({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{/allParams.0}}): Promise; + {{nickname}}RequestOpts({{#contentTypeMerged}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{#hasContentTypeResponseVariants}} & { accept?: string }{{/hasContentTypeResponseVariants}}{{/contentTypeMerged}}{{^contentTypeMerged}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{/allParams.0}}{{/contentTypeMerged}}): Promise; {{/withRequestOptsInInterface}} /** @@ -72,7 +86,14 @@ export interface {{classname}}Interface { * @throws {RequiredError} * @memberof {{classname}}Interface */ + {{#hasContentTypeResponseVariants}} + {{#contentTypeResponseVariants}} + {{nickname}}Raw(requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request & { accept{{#isDefault}}?{{/isDefault}}: '{{mediaType}}' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + {{/contentTypeResponseVariants}} + {{/hasContentTypeResponseVariants}} + {{^hasContentTypeResponseVariants}} {{nickname}}Raw({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + {{/hasContentTypeResponseVariants}} /** {{#notes}} @@ -89,7 +110,14 @@ export interface {{classname}}Interface { {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{#isNullable}} | null{{/isNullable}}{{/isEnum}}, {{/allParams}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}>; {{/useSingleRequestParameter}} {{#useSingleRequestParameter}} + {{#hasContentTypeResponseVariants}} + {{#contentTypeResponseVariants}} + {{nickname}}(requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request & { accept{{#isDefault}}?{{/isDefault}}: '{{mediaType}}' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{#returnType}}{{{returnType}}}{{#isResponseOptional}} | null | undefined{{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}>; + {{/contentTypeResponseVariants}} + {{/hasContentTypeResponseVariants}} + {{^hasContentTypeResponseVariants}} {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}>; + {{/hasContentTypeResponseVariants}} {{/useSingleRequestParameter}} {{/operation}} @@ -115,9 +143,17 @@ export class {{classname}} extends runtime.BaseAPI { * @deprecated {{/isDeprecated}} */ - async {{nickname}}RequestOpts({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{/allParams.0}}): Promise { + async {{nickname}}RequestOpts({{#contentTypeMerged}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{#hasContentTypeResponseVariants}} & { accept?: string }{{/hasContentTypeResponseVariants}}{{/contentTypeMerged}}{{^contentTypeMerged}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{/allParams.0}}{{/contentTypeMerged}}): Promise { + {{! the conditional has to sit outside the parameter loop below: in a parameter's context, + `vendorExtensions` resolves to that parameter's own map and never to the operation's }} + {{#hasContentTypeRequestVariants}} {{#allParams}} {{#required}} + {{! the body and the form params only exist on one member of the request union: indexing them + here would not type-check, would narrow the union for everything below - and would demand + of every content-type a parameter only one of them has. Guarded in the switch instead. }} + {{^isBodyParam}} + {{^isFormParam}} if (requestParameters['{{paramName}}'] == null) { throw new runtime.RequiredError( '{{paramName}}', @@ -125,8 +161,24 @@ export class {{classname}} extends runtime.BaseAPI { ); } + {{/isFormParam}} + {{/isBodyParam}} {{/required}} {{/allParams}} + {{/hasContentTypeRequestVariants}} + {{^hasContentTypeRequestVariants}} + {{#allParams}} + {{#required}} + if (requestParameters['{{paramName}}'] == null) { + throw new runtime.RequiredError( + '{{paramName}}', + 'Required parameter "{{paramName}}" was null or undefined when calling {{nickname}}().' + ); + } + + {{/required}} + {{/allParams}} + {{/hasContentTypeRequestVariants}} const queryParameters: any = {}; {{#queryParams}} @@ -162,6 +214,15 @@ export class {{classname}} extends runtime.BaseAPI { {{/queryParams}} const headerParameters: runtime.HTTPHeaders = {}; + {{! Content-Type is set per content-type in the switch below, where the body is built: a multipart + body must not set it at all, fetch adds it with the boundary it generates }} + {{! only where the response axis was actually divided: elsewhere the caller may have pinned an + Accept on the Configuration, and an operation-level one silently wins over it }} + {{#hasContentTypeResponseVariants}} + headerParameters['Accept'] = requestParameters.accept ?? '{{vendorExtensions.x-content-type-default-response}}'; + + {{/hasContentTypeResponseVariants}} + {{^hasContentTypeRequestVariants}} {{#bodyParam}} {{^consumes}} headerParameters['Content-Type'] = 'application/json'; @@ -172,6 +233,7 @@ export class {{classname}} extends runtime.BaseAPI { {{/consumes.0}} {{/bodyParam}} + {{/hasContentTypeRequestVariants}} {{#headerParams}} {{#isArray}} if (requestParameters['{{paramName}}'] != null) { @@ -226,75 +288,15 @@ export class {{classname}} extends runtime.BaseAPI { {{/isOAuth}} {{/authMethods}} + {{! a request-split operation assembles its form body inside the content-type switch instead, where + the union is narrowed; emitting it here too would shadow those declarations }} + {{^hasContentTypeRequestVariants}} {{#hasFormParams}} - const consumes: runtime.Consume[] = [ - {{#consumes}} - { contentType: '{{{mediaType}}}' }, - {{/consumes}} - ]; - // @ts-ignore: canConsumeForm may be unused - const canConsumeForm = runtime.canConsumeForm(consumes); - - let formParams: { append(param: string, value: any): any }; - let useForm = false; - {{#formParams}} - {{#isFile}} - // use FormData to transmit files using content-type "multipart/form-data" - useForm = canConsumeForm; - {{/isFile}} - {{/formParams}} - if (useForm) { - formParams = new FormData(); - } else { - formParams = new URLSearchParams(); - } - - {{#formParams}} - {{#isArray}} - if (requestParameters['{{paramName}}'] != null) { - {{#isCollectionFormatMulti}} - requestParameters['{{paramName}}'].forEach((element) => { - formParams.append('{{baseName}}{{#useSquareBracketsInArrayNames}}[]{{/useSquareBracketsInArrayNames}}', element as any); - }) - {{/isCollectionFormatMulti}} - {{^isCollectionFormatMulti}} - formParams.append('{{baseName}}{{#useSquareBracketsInArrayNames}}[]{{/useSquareBracketsInArrayNames}}', {{#uniqueItems}}Array.from({{/uniqueItems}}requestParameters['{{paramName}}']{{#uniqueItems}}){{/uniqueItems}}!.join(runtime.COLLECTION_FORMATS["{{collectionFormat}}"])); - {{/isCollectionFormatMulti}} - } - - {{/isArray}} - {{^isArray}} - if (requestParameters['{{paramName}}'] != null) { - {{#isDateTimeType}} - formParams.append('{{baseName}}', (requestParameters['{{paramName}}'] as any).toISOString()); - {{/isDateTimeType}} - {{^isDateTimeType}} - {{#isPrimitiveType}} - formParams.append('{{baseName}}', requestParameters['{{paramName}}'] as any); - {{/isPrimitiveType}} - {{^isPrimitiveType}} - {{#isEnumRef}} - formParams.append('{{baseName}}', requestParameters['{{paramName}}'] as any); - {{/isEnumRef}} - {{^isEnumRef}} - {{^withoutRuntimeChecks}} - {{^isContainer}} - formParams.append('{{baseName}}', new Blob([JSON.stringify({{{dataType}}}ToJSON(requestParameters['{{paramName}}']))], { type: "application/json", })); - {{/isContainer}} - {{#isContainer}} - formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", })); - {{/isContainer}} - {{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}} - formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", })); - {{/withoutRuntimeChecks}} - {{/isEnumRef}} - {{/isPrimitiveType}} - {{/isDateTimeType}} - } - - {{/isArray}} - {{/formParams}} +{{! the partial is already written at this method's indentation, so it is included as-is; the + content-type switch, which is deeper, is the one that has to re-indent it }} +{{>apisFormParams}} {{/hasFormParams}} + {{/hasContentTypeRequestVariants}} let urlPath = `{{{path}}}`; {{#pathParams}} @@ -319,6 +321,37 @@ export class {{classname}} extends runtime.BaseAPI { {{/isDateTimeType}} {{/pathParams}} + {{#hasContentTypeRequestVariants}} + {{! `contentType` selects the body's type, so narrow on it before serialising }} + let body: any; + switch (requestParameters.contentType) { + {{#contentTypeRequestVariants}} + {{^isDefault}} + case '{{mediaType}}': { +{{>apisContentTypeVariantBody}} + break; + } + {{/isDefault}} + {{/contentTypeRequestVariants}} + {{#contentTypeRequestVariants}} + {{#isDefault}} + default: { +{{>apisContentTypeVariantBody}} + } + {{/isDefault}} + {{/contentTypeRequestVariants}} + } + + return { + path: urlPath, + method: '{{httpMethod}}', + headers: headerParameters, + query: queryParameters, + body: body, + }; + } + {{/hasContentTypeRequestVariants}} + {{^hasContentTypeRequestVariants}} return { path: urlPath, method: '{{httpMethod}}', @@ -326,27 +359,7 @@ export class {{classname}} extends runtime.BaseAPI { query: queryParameters, {{#hasBodyParam}} {{#bodyParam}} - {{#isContainer}} - {{^withoutRuntimeChecks}} - body: requestParameters['{{paramName}}']{{#isArray}}{{#items}}{{^isPrimitiveType}}!.map({{datatype}}ToJSON){{/isPrimitiveType}}{{/items}}{{/isArray}}, - {{/withoutRuntimeChecks}} - {{#withoutRuntimeChecks}} - body: requestParameters['{{paramName}}'], - {{/withoutRuntimeChecks}} - {{/isContainer}} - {{^isContainer}} - {{^isPrimitiveType}} - {{^withoutRuntimeChecks}} - body: {{dataType}}ToJSON(requestParameters['{{paramName}}']), - {{/withoutRuntimeChecks}} - {{#withoutRuntimeChecks}} - body: requestParameters['{{paramName}}'], - {{/withoutRuntimeChecks}} - {{/isPrimitiveType}} - {{#isPrimitiveType}} - body: requestParameters['{{paramName}}'] as any, - {{/isPrimitiveType}} - {{/isContainer}} + body: {{>apisRequestBodyValue}}, {{/bodyParam}} {{/hasBodyParam}} {{#hasFormParams}} @@ -354,6 +367,7 @@ export class {{classname}} extends runtime.BaseAPI { {{/hasFormParams}} }; } + {{/hasContentTypeRequestVariants}} /** {{#notes}} @@ -366,6 +380,39 @@ export class {{classname}} extends runtime.BaseAPI { * @deprecated {{/isDeprecated}} */ + {{#hasContentTypeResponseVariants}} + {{! one overload per response content-type: `accept` selects the return type. The implementation + signature unions them and is not callable from outside. }} + {{#contentTypeResponseVariants}} + async {{nickname}}Raw(requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request & { accept{{#isDefault}}?{{/isDefault}}: '{{mediaType}}' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + {{/contentTypeResponseVariants}} + async {{nickname}}Raw(requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.{{nickname}}RequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + {{! dispatch on the content-type the server actually returned, not on the requested `accept`: + the header is a request, and a server is free not to honour it }} + {{! type/subtype only, compared exactly: startsWith would let application/json win over + application/json-patch+json, and a `; charset=` parameter would defeat an equality test }} + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + {{#contentTypeResponseDispatch}} + {{#-first}} + if (responseContentType === '{{mediaType}}') { + {{/-first}} + {{^-first}} + {{^-last}} + } else if (responseContentType === '{{mediaType}}') { + {{/-last}} + {{/-first}} + {{#-last}} + } else { + {{/-last}} +{{>apisResponseVariantValue}} + {{/contentTypeResponseDispatch}} + } + } + {{/hasContentTypeResponseVariants}} + {{^hasContentTypeResponseVariants}} async {{nickname}}Raw({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { const requestOptions = await this.{{nickname}}RequestOpts({{#allParams.0}}requestParameters{{/allParams.0}}); const response = await this.request(requestOptions, initOverrides); @@ -409,6 +456,7 @@ export class {{classname}} extends runtime.BaseAPI { return new runtime.VoidApiResponse(response); {{/returnType}} } + {{/hasContentTypeResponseVariants}} /** {{#notes}} @@ -447,6 +495,34 @@ export class {{classname}} extends runtime.BaseAPI { } {{/useSingleRequestParameter}} {{#useSingleRequestParameter}} + {{#hasContentTypeResponseVariants}} + {{#contentTypeResponseVariants}} + async {{nickname}}(requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request & { accept{{#isDefault}}?{{/isDefault}}: '{{mediaType}}' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{#returnType}}{{{returnType}}}{{#isResponseOptional}} | null | undefined{{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}>; + {{/contentTypeResponseVariants}} + async {{nickname}}(requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{#contentTypeResponseVariants}}{{{returnType}}}{{^returnType}}void{{/returnType}}{{^-last}} | {{/-last}}{{/contentTypeResponseVariants}}{{#isResponseOptional}} | null | undefined{{/isResponseOptional}}> { + {{! `as any`: from the outside only the overloads of ...Raw are visible, and the loose `accept` + accepted here matches none of them }} + const response = await this.{{nickname}}Raw(requestParameters as any, initOverrides); + {{#isResponseOptional}} + {{! a 2xx response with no body (a 204, typically) has nothing to deserialise: give back null, + the way the unmerged path does }} + switch (response.raw.status) { + {{#responses}} + {{#is2xx}} + case {{code}}: + return {{#dataType}}await response.value(){{/dataType}}{{^dataType}}null{{/dataType}}; + {{/is2xx}} + {{/responses}} + default: + return await response.value(); + } + {{/isResponseOptional}} + {{^isResponseOptional}} + return await response.value(); + {{/isResponseOptional}} + } + {{/hasContentTypeResponseVariants}} + {{^hasContentTypeResponseVariants}} async {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, {{/allParams.0}}initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{{{returnType}}}{{#returnType}}{{#isResponseOptional}} | null | undefined {{/isResponseOptional}}{{/returnType}}{{^returnType}}void{{/returnType}}> { {{#returnType}} const response = await this.{{nickname}}Raw({{#allParams.0}}requestParameters, {{/allParams.0}}initOverrides); @@ -470,6 +546,7 @@ export class {{classname}} extends runtime.BaseAPI { await this.{{nickname}}Raw({{#allParams.0}}requestParameters, {{/allParams.0}}initOverrides); {{/returnType}} } + {{/hasContentTypeResponseVariants}} {{/useSingleRequestParameter}} {{/operation}} @@ -479,36 +556,20 @@ export class {{classname}} extends runtime.BaseAPI { {{#operations}} {{#operation}} +{{^contentTypeMerged}} {{#allParams}} {{#isEnum}} -{{#stringEnums}} -/** - * @export - * @enum {string} - */ -export enum {{operationIdCamelCase}}{{enumName}} { -{{#allowableValues}} - {{#enumVars}} - {{{name}}} = {{{value}}}{{^-last}},{{/-last}} - {{/enumVars}} -{{/allowableValues}} -} -{{/stringEnums}} -{{^stringEnums}} -/** - * @export - */ -export const {{operationIdCamelCase}}{{enumName}} = { -{{#allowableValues}} - {{#enumVars}} - {{{name}}}: {{{value}}}{{^-last}},{{/-last}} - {{/enumVars}} -{{/allowableValues}} -} as const; -export type {{operationIdCamelCase}}{{enumName}} = typeof {{operationIdCamelCase}}{{enumName}}[keyof typeof {{operationIdCamelCase}}{{enumName}}]; -{{/stringEnums}} +{{>apisOperationEnum}} {{/isEnum}} {{/allParams}} +{{/contentTypeMerged}} +{{#contentTypeMerged}} +{{! the request union references every variant's parameters, allParams only holds the surviving + variant's: the merge collected the enum ones across all the variants, deduplicated }} +{{#contentTypeMergedEnumParams}} +{{>apisOperationEnum}} +{{/contentTypeMergedEnumParams}} +{{/contentTypeMerged}} {{/operation}} {{/operations}} {{/hasEnums}} diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache new file mode 100644 index 000000000000..8c47b80c237e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache @@ -0,0 +1,33 @@ +{{! Builds the body of one request content-type variant, inside its case of the content-type switch, where + the request union is narrowed to that variant's member. Context: a request variant entry. }} +{{#hasFormParams}} +{{! required form params are guarded here rather than before the switch: they only exist on this + member of the request union, the other content-types do not have them }} +{{#formParams}} +{{#required}} + if (requestParameters['{{paramName}}'] == null) { + throw new runtime.RequiredError( + '{{paramName}}', + 'Required parameter "{{paramName}}" was null or undefined when calling {{nickname}}().' + ); + } +{{/required}} +{{/formParams}} +{{#lambda.indented_8_skip_blank}}{{>apisFormParams}}{{/lambda.indented_8_skip_blank}} + {{! a multipart body sets no Content-Type: fetch adds it with the boundary it generates }} + body = formParams; +{{/hasFormParams}} +{{^hasFormParams}} + headerParameters['Content-Type'] = '{{mediaType}}'; +{{#bodyParam}} +{{#required}} + if (requestParameters['{{paramName}}'] == null) { + throw new runtime.RequiredError( + '{{paramName}}', + 'Required parameter "{{paramName}}" was null or undefined when calling {{nickname}}().' + ); + } +{{/required}} +{{/bodyParam}} + body = {{#bodyParam}}{{>apisRequestBodyValue}}{{/bodyParam}}{{^bodyParam}}undefined{{/bodyParam}}; +{{/hasFormParams}} diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apisFormParams.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apisFormParams.mustache new file mode 100644 index 000000000000..10199c1f3fd8 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apisFormParams.mustache @@ -0,0 +1,67 @@ + const consumes: runtime.Consume[] = [ + {{#consumes}} + { contentType: '{{{mediaType}}}' }, + {{/consumes}} + ]; + // @ts-ignore: canConsumeForm may be unused + const canConsumeForm = runtime.canConsumeForm(consumes); + + let formParams: { append(param: string, value: any): any }; + let useForm = false; + {{#formParams}} + {{#isFile}} + // use FormData to transmit files using content-type "multipart/form-data" + useForm = canConsumeForm; + {{/isFile}} + {{/formParams}} + if (useForm) { + formParams = new FormData(); + } else { + formParams = new URLSearchParams(); + } + + {{#formParams}} + {{#isArray}} + if (requestParameters['{{paramName}}'] != null) { + {{#isCollectionFormatMulti}} + requestParameters['{{paramName}}'].forEach((element) => { + formParams.append('{{baseName}}{{#useSquareBracketsInArrayNames}}[]{{/useSquareBracketsInArrayNames}}', element as any); + }) + {{/isCollectionFormatMulti}} + {{^isCollectionFormatMulti}} + formParams.append('{{baseName}}{{#useSquareBracketsInArrayNames}}[]{{/useSquareBracketsInArrayNames}}', {{#uniqueItems}}Array.from({{/uniqueItems}}requestParameters['{{paramName}}']{{#uniqueItems}}){{/uniqueItems}}!.join(runtime.COLLECTION_FORMATS["{{collectionFormat}}"])); + {{/isCollectionFormatMulti}} + } + + {{/isArray}} + {{^isArray}} + if (requestParameters['{{paramName}}'] != null) { + {{#isDateTimeType}} + formParams.append('{{baseName}}', (requestParameters['{{paramName}}'] as any).toISOString()); + {{/isDateTimeType}} + {{^isDateTimeType}} + {{#isPrimitiveType}} + formParams.append('{{baseName}}', requestParameters['{{paramName}}'] as any); + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isEnumRef}} + formParams.append('{{baseName}}', requestParameters['{{paramName}}'] as any); + {{/isEnumRef}} + {{^isEnumRef}} + {{^withoutRuntimeChecks}} + {{^isContainer}} + formParams.append('{{baseName}}', new Blob([JSON.stringify({{{dataType}}}ToJSON(requestParameters['{{paramName}}']))], { type: "application/json", })); + {{/isContainer}} + {{#isContainer}} + formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", })); + {{/isContainer}} + {{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}} + formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", })); + {{/withoutRuntimeChecks}} + {{/isEnumRef}} + {{/isPrimitiveType}} + {{/isDateTimeType}} + } + + {{/isArray}} + {{/formParams}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apisOperationEnum.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apisOperationEnum.mustache new file mode 100644 index 000000000000..e1641254e521 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apisOperationEnum.mustache @@ -0,0 +1,28 @@ +{{! Declares the enum type of one operation parameter, named after the operation. Context: an enum + parameter, with its operation up the stack. Written flush left, like the enums it replaces. }} +{{#stringEnums}} +/** + * @export + * @enum {string} + */ +export enum {{operationIdCamelCase}}{{enumName}} { +{{#allowableValues}} + {{#enumVars}} + {{{name}}} = {{{value}}}{{^-last}},{{/-last}} + {{/enumVars}} +{{/allowableValues}} +} +{{/stringEnums}} +{{^stringEnums}} +/** + * @export + */ +export const {{operationIdCamelCase}}{{enumName}} = { +{{#allowableValues}} + {{#enumVars}} + {{{name}}}: {{{value}}}{{^-last}},{{/-last}} + {{/enumVars}} +{{/allowableValues}} +} as const; +export type {{operationIdCamelCase}}{{enumName}} = typeof {{operationIdCamelCase}}{{enumName}}[keyof typeof {{operationIdCamelCase}}{{enumName}}]; +{{/stringEnums}} diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apisRequestBodyValue.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apisRequestBodyValue.mustache new file mode 100644 index 000000000000..25a11a08256c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apisRequestBodyValue.mustache @@ -0,0 +1,3 @@ +{{! Serialised value of a body parameter. Context: a bodyParam. Used by the content-type variant switch, + which needs the same expression once per request content-type. }} +{{#isContainer}}requestParameters['{{paramName}}']{{^withoutRuntimeChecks}}{{#isArray}}{{#items}}{{^isPrimitiveType}}!.map({{datatype}}ToJSON){{/isPrimitiveType}}{{/items}}{{/isArray}}{{/withoutRuntimeChecks}}{{/isContainer}}{{^isContainer}}{{#isPrimitiveType}}requestParameters['{{paramName}}'] as any{{/isPrimitiveType}}{{^isPrimitiveType}}{{^withoutRuntimeChecks}}{{dataType}}ToJSON(requestParameters['{{paramName}}']){{/withoutRuntimeChecks}}{{#withoutRuntimeChecks}}requestParameters['{{paramName}}']{{/withoutRuntimeChecks}}{{/isPrimitiveType}}{{/isContainer}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apisResponseVariantValue.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apisResponseVariantValue.mustache new file mode 100644 index 000000000000..0995bdc9a2b7 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apisResponseVariantValue.mustache @@ -0,0 +1,42 @@ +{{! Deserialisation of one response content-type variant. Context: the variant operation, so returnType and + friends are the ones the generator resolved natively for that content-type. `as any` is unavoidable: the + implementation signature returns the union of every variant's type, and TypeScript cannot prove which + branch the runtime content-type took. }} +{{#returnType}} +{{#isResponseFile}} + return new runtime.BlobApiResponse(response) as any; +{{/isResponseFile}} +{{^isResponseFile}} +{{#returnTypeIsPrimitive}} +{{#isMap}} + return new runtime.JSONApiResponse(response) as any; +{{/isMap}} +{{#isArray}} + return new runtime.JSONApiResponse(response) as any; +{{/isArray}} +{{#returnSimpleType}} + if (this.isJsonMime(responseContentType)) { + return new runtime.JSONApiResponse<{{returnType}}>(response) as any; + } else { + return new runtime.TextApiResponse(response) as any; + } +{{/returnSimpleType}} +{{/returnTypeIsPrimitive}} +{{^returnTypeIsPrimitive}} +{{#isArray}} + return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, (jsonValue) => {{#uniqueItems}}new Set({{/uniqueItems}}jsonValue.map({{returnBaseType}}FromJSON){{/withoutRuntimeChecks}}){{#uniqueItems}}){{/uniqueItems}} as any; +{{/isArray}} +{{^isArray}} +{{#isMap}} + return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, (jsonValue) => runtime.mapValues(jsonValue, {{returnBaseType}}FromJSON){{/withoutRuntimeChecks}}) as any; +{{/isMap}} +{{^isMap}} + return new runtime.JSONApiResponse(response{{^withoutRuntimeChecks}}, (jsonValue) => {{returnBaseType}}FromJSON(jsonValue){{/withoutRuntimeChecks}}) as any; +{{/isMap}} +{{/isArray}} +{{/returnTypeIsPrimitive}} +{{/isResponseFile}} +{{/returnType}} +{{^returnType}} + return new runtime.VoidApiResponse(response) as any; +{{/returnType}} diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache index 00ca3b3ee0ac..2c2c90105ada 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache @@ -294,6 +294,21 @@ export const COLLECTION_FORMATS = { export type FetchAPI = WindowOrWorkerGlobalScope['fetch']; +{{#splitOperationsByContentType}} +type AllKeys = T extends unknown ? keyof T : never; +/** + * Makes the members of a union mutually exclusive, by declaring on each of them the keys it does not have + * as `never`. Without it a member is satisfied by a value carrying another member's keys: assignability is + * structural and tolerates surplus properties, and excess property checking never fires against a union + * since a key present in any member counts as known. + * + * `U` distributes while `T` stays the whole union, which is what lets each member see the others' keys. + */ +export type ExclusiveUnion = U extends unknown + ? U & Partial, keyof U>, never>> + : never; + +{{/splitOperationsByContentType}} export type Json = any; export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; export type HTTPHeaders = { [key: string]: string }; diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index acdb0efcadbc..b64afddd6539 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -58,6 +58,7 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; import static org.junit.jupiter.api.Assertions.*; import static org.openapitools.codegen.CodegenConstants.X_ENUM_DESCRIPTIONS; import static org.openapitools.codegen.CodegenConstants.X_ENUM_VARNAMES; @@ -5281,4 +5282,52 @@ public void splitOperationsByContentTypeUsesTheMethodResponse() { Operation getB = openAPI.getPaths().get("/b").getGet(); assertThat(codegen.divideOperationsByContentType(openAPI, "/b", "get", getB)).containsExactly(getB); } + + @Test + public void splitOperationsByContentTypeTagsEveryVariant() { + DefaultCodegen codegen = new DefaultCodegen(); + codegen.setSplitOperationsByContentType(true); + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/issue6708-split-by-content-type.yaml"); + + Operation post = openAPI.getPaths().get("/reports").getPost(); + List variants = codegen.divideOperationsByContentType(openAPI, "/reports", "post", post); + + assertThat(variants).allSatisfy(variant -> assertThat(variant.getExtensions()) + .containsEntry(CodegenConstants.X_CONTENT_TYPE_VARIANT_GROUP, "createReport")); + + // each variant records the content-type it was narrowed to on each axis and its rank there. Rank 0 is + // the content-type the spec declares first, which is the default one, so a generator merging the + // variants back together never has to rely on the order it happens to receive them in. + assertThat(variants).extracting( + v -> v.getExtensions().get(CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST), + v -> v.getExtensions().get(CodegenConstants.X_CONTENT_TYPE_VARIANT_REQUEST_INDEX), + v -> v.getExtensions().get(CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE), + v -> v.getExtensions().get(CodegenConstants.X_CONTENT_TYPE_VARIANT_RESPONSE_INDEX)) + .containsExactlyInAnyOrder( + tuple("application/json", 0, "application/json", 0), + tuple("application/json", 0, "application/pdf", 1), + tuple("application/xml", 1, "application/json", 0), + tuple("application/xml", 1, "application/pdf", 1)); + } + + @Test + public void splitOperationsByContentTypeIsAGlobalOption() { + // the behaviour is language-neutral, so the option is global rather than declared - and documented - + // by every single generator + assertThat(new DefaultCodegen().cliOptions()).extracting(CliOption::getOpt) + .doesNotContain(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE); + + try { + GlobalSettings.setProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true"); + DefaultCodegen codegen = new DefaultCodegen(); + codegen.processOpts(); + assertThat(codegen.splitOperationsByContentType).isTrue(); + } finally { + GlobalSettings.clearProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE); + } + + DefaultCodegen off = new DefaultCodegen(); + off.processOpts(); + assertThat(off.splitOperationsByContentType).isFalse(); + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java index 95a43280b62b..76b523fcd728 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/BashClientOptionsProvider.java @@ -67,7 +67,6 @@ public Map createOptions() { .put(BashClientCodegen.APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME, APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "false") - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, "false") .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "false") .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java index 4e344a9c69d7..e8ae5313da8b 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartClientOptionsProvider.java @@ -53,7 +53,6 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(DartClientCodegen.PUB_LIBRARY, PUB_LIBRARY_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java index a26b64363334..a8e0f8381df0 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java @@ -52,7 +52,6 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(DartDioClientCodegen.PUB_LIBRARY, PUB_LIBRARY_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java index 691805e2f913..32b7b3d34151 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ElixirClientOptionsProvider.java @@ -37,7 +37,6 @@ public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "false") - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, "false") .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "false") .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, "false") diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java index 80ef8ae9a544..b6cb61abc193 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellServantOptionsProvider.java @@ -44,7 +44,6 @@ public Map createOptions() { return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java index 04b9b39dae30..66fd08f19aaa 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/HaskellYesodServerOptionsProvider.java @@ -25,7 +25,6 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java index 89368c3f91ed..bf26ac750fa7 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpClientOptionsProvider.java @@ -55,7 +55,6 @@ public Map createOptions() { return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(PhpClientCodegen.VARIABLE_NAMING_CONVENTION, VARIABLE_NAMING_CONVENTION_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java index c76041e23b84..ee795a038735 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpLumenServerOptionsProvider.java @@ -57,7 +57,6 @@ public Map createOptions() { .put(AbstractPhpCodegen.SRC_BASE_PATH, SRC_BASE_PATH_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java index cd261da45a67..7ebaece2aae3 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/PhpSlim4ServerOptionsProvider.java @@ -61,7 +61,6 @@ public Map createOptions() { .put(CodegenConstants.INVOKER_PACKAGE, INVOKER_PACKAGE_VALUE) .put(CodegenConstants.ARTIFACT_VERSION, ARTIFACT_VERSION_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java index 0c069c6f316a..4578b058af70 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/RubyClientOptionsProvider.java @@ -64,7 +64,6 @@ public Map createOptions() { .put(RubyClientCodegen.GEM_AUTHOR_EMAIL, GEM_AUTHOR_EMAIL_VALUE) .put(RubyClientCodegen.GEM_METADATA, GEM_METADATA_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, "true") diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java index 94f10a5daf0a..7c4e5d4a1b92 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/ScalaAkkaClientOptionsProvider.java @@ -48,7 +48,6 @@ public Map createOptions() { return builder.put(CodegenConstants.MODEL_PACKAGE, MODEL_PACKAGE_VALUE) .put(CodegenConstants.API_PACKAGE, API_PACKAGE_VALUE) .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java index 3fcab35754a7..3485cc879032 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift5OptionsProvider.java @@ -68,7 +68,6 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(Swift5ClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java index 4da0f6b43cf8..e470c5646c00 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/Swift6ClientCodegenOptionsProvider.java @@ -70,7 +70,6 @@ public String getLanguage() { public Map createOptions() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE) .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) .put(Swift6ClientCodegen.PROJECT_NAME, PROJECT_NAME_VALUE) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java index 14df72eae70e..be020be5a7bb 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptSharedClientOptionsProvider.java @@ -49,7 +49,6 @@ default Map createOptions() { entry(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE, ENUM_UNKNOWN_DEFAULT_CASE_VALUE), entry(AbstractTypeScriptClientCodegen.ENUM_PROPERTY_NAMING_REPLACE_SPECIAL_CHAR, ENUM_PROPERTY_NAMING_REPLACE_SPECIAL_CHAR_VALUE), entry(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE), - entry(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false"), entry(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, SORT_MODEL_PROPERTIES_VALUE), entry(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE), entry(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, LEGACY_DISCRIMINATOR_BEHAVIOUR_VALUE), diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java index b2beb3ef243d..a7f9a8697658 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/XojoClientOptionsProvider.java @@ -54,7 +54,6 @@ public Map createOptions() { .put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true") .put(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG, "true") .put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "true") - .put(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "false") .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, "true") .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, "false") .put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "false") diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java index 094929f2fe53..1971536a362c 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java @@ -67,6 +67,291 @@ public void testOptionalResponseImports() { Assert.assertEquals(operation.isResponseOptional, true); } + @Test + public void testMergesContentTypeVariantsIntoOneMethod() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + Path api = Paths.get(output + "/apis/ReportApi.ts"); + + // the split emitted four operations for POST /reports (2 request x 2 response content-types); + // TypeScript expresses the whole matrix at once, so a single method survives + TestUtils.assertFileNotContains(api, "createReportWithJsonAsJson", "createReportWithXmlAsPdf"); + + // request axis: a union discriminated by contentType, whose value selects the body's type. The + // content-type declared first is the default one, hence optional. + TestUtils.assertFileContains(api, + "runtime.ExclusiveUnion<", + "| { contentType?: 'application/json'; report?: Report; }", + "| { contentType: 'application/xml'; reportXml?: ReportXml; }"); + + // response axis: one overload per content-type, `accept` selecting the return type + TestUtils.assertFileContains(api, + "async createReportRaw(requestParameters: CreateReportRequest & { accept?: 'application/json' }", + "async createReportRaw(requestParameters: CreateReportRequest & { accept: 'application/pdf' }", + "Promise>"); + + // Content-Type is set inside the branch that builds the body, Accept defaults to the response + // content-type declared first, and deserialisation dispatches on what the server actually returned + // rather than on the requested accept + TestUtils.assertFileContains(api, + " headerParameters['Content-Type'] = 'application/xml';", + " headerParameters['Content-Type'] = 'application/json';", + "headerParameters['Accept'] = requestParameters.accept ?? 'application/json';", + "if (responseContentType === 'application/pdf') {"); + } + + @Test + public void testRequestUnionExcludesTheOtherVariantsBodies() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-required-body.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + Path api = Paths.get(output + "/apis/ReportApi.ts"); + + // runtime.ExclusiveUnion makes the members mutually exclusive, without which an XML body handed to + // the JSON member is silently sent as JSON. Excess property checking never fires against a union - a + // key present in any member counts as known - and the checks that do reject most shapes (weak type + // detection, a missing required property) leave out a member with a required parameter and an + // optional body, as createDraft has. + TestUtils.assertFileContains(api, + "export type CreateDraftRequest = runtime.ExclusiveUnion<", + "| { contentType?: 'application/json'; projectId: string; report?: Report; }", + "| { contentType: 'application/xml'; projectId: string; reportXml?: ReportXml; }"); + + // A required body only exists on one member of the union, so it cannot be guarded before the switch: + // indexing it there would not type-check, and would narrow the union for everything below. + TestUtils.assertFileContains(api, + " if (requestParameters['reportXml'] == null) {", + " if (requestParameters['report'] == null) {"); + + String content = Files.readString(api); + int requestOpts = content.indexOf("async createProjectReportRequestOpts"); + int contentTypeSwitch = content.indexOf("switch (requestParameters.contentType)", requestOpts); + assertThat(content.substring(requestOpts, contentTypeSwitch)) + .as("the body must not be indexed before the content-type is known") + .doesNotContain("requestParameters['report']"); + } + + @Test + public void testEnumParameterFollowsTheMergedOperationName() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-enum-param.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + // An enum parameter's type is named after its operation, and the enum is declared once. The merge + // renames the operation, so both sides have to end up on the merged name - the request union + // references every variant's parameters, not just the surviving one's. + Path api = Paths.get(output + "/apis/OrderApi.ts"); + TestUtils.assertFileContains(api, + "| { orderBy?: GetOrdersOrderByEnum; }", + "export const GetOrdersOrderByEnum = {"); + } + + @Test + public void testMergedOperationKeepsTheOptionalResponseBehaviour() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-optional-response.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + // the operation can answer 204 as well as 200: the unmerged path returns null for the bodyless + // status instead of parsing an empty body, and the merged one has to do the same + Path api = Paths.get(output + "/apis/ReportApi.ts"); + TestUtils.assertFileContains(api, + "async getReport(requestParameters: GetReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise;", + "async getReport(requestParameters: GetReportRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise;", + "switch (response.raw.status) {", + " case 204:", + " return null;"); + } + + @Test + public void testRequiredFormParameterIsOnlyEnforcedOnItsOwnContentType() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-required-form.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + // `file` is required by the multipart variant only: guarded inside its branch of the content-type + // switch, not before it, where it would throw on a perfectly valid application/json call + Path api = Paths.get(output + "/apis/FilesApi.ts"); + String content = Files.readString(api); + int requestOpts = content.indexOf("async convertRequestOpts"); + int contentTypeSwitch = content.indexOf("switch (requestParameters.contentType)", requestOpts); + assertThat(content.substring(requestOpts, contentTypeSwitch)) + .as("a form parameter must not be enforced before the content-type is known") + .doesNotContain("requestParameters['file'] == null"); + + // multipart was declared first, so its branch is the switch's default case + int defaultCase = content.indexOf("default: {", contentTypeSwitch); + TestUtils.assertFileContains(api, "Required parameter \"file\" was null or undefined"); + assertThat(content.indexOf("requestParameters['file'] == null", defaultCase)) + .as("the guard belongs inside the multipart branch") + .isGreaterThan(defaultCase); + } + + @Test + public void testEnumOfADroppedVariantIsStillDeclared() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-variant-enum.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + // the `mode` enum only exists on the multipart variant, which the merge drops: the union still + // references its type, so the declaration has to be collected from the dropped variant + Path api = Paths.get(output + "/apis/FilesApi.ts"); + TestUtils.assertFileContains(api, + "mode?: ConvertModeEnum;", + "export const ConvertModeEnum = {"); + + // and declared exactly once, even when several variants share the parameter + String content = Files.readString(api); + String declaration = "export const ConvertModeEnum = {"; + assertThat(content.indexOf(declaration)).isEqualTo(content.lastIndexOf(declaration)); + } + + @Test + public void testMergedOperationNameIsEscapedAgainstImportedModels() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-name-collision.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + // The spec imports a model named CreateReportRequest into an API whose merged operation is + // createReport. escapeOperationIds ran on the variants' suffixed names and saw no clash, so the + // merge has to replay its escape on the merged name - the same one the unsplit path would emit. + Path api = Paths.get(output + "/apis/ReportApi.ts"); + TestUtils.assertFileContains(api, + "export type CreateReportOperationRequest = runtime.ExclusiveUnion<", + "async createReport(requestParameters: CreateReportOperationRequest"); + TestUtils.assertFileNotContains(api, + "export type CreateReportRequest =", + "export interface CreateReportRequest"); + } + + @Test + public void testMergesFormAndMultipartVariants() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type-form.yaml") + .addGlobalProperty(CodegenConstants.SPLIT_OPERATIONS_BY_CONTENT_TYPE, "true") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + Path api = Paths.get(output + "/apis/FilesApi.ts"); + + // POST /upload has a single, multipart request content-type and two response content-types: only the + // response axis is split, and merging it just adds `accept` to the request object. + TestUtils.assertFileNotContains(api, "uploadAsJson", "uploadAsPdf"); + + // Accept is emitted only where the response axis was divided: elsewhere a caller may have pinned + // one on the Configuration, and an operation-level header silently wins over it. + TestUtils.assertFileContains(api, + "headerParameters['Accept'] = requestParameters.accept ?? 'application/json';"); + TestUtils.assertFileContains(api, + "async upload(requestParameters: UploadRequest & { accept?: 'application/json' }", + "async upload(requestParameters: UploadRequest & { accept: 'application/pdf' }"); + + // POST /convert accepts both application/json and multipart/form-data. A form body is spread over + // individual parameters rather than gathered in one, so the union member carries them as they are + // and the body is assembled inside that content-type's branch. + TestUtils.assertFileNotContains(api, "convertWithJson", "convertWithFormData"); + TestUtils.assertFileContains(api, + "| { contentType?: 'application/json'; receipt?: Receipt; }", + "| { contentType: 'multipart/form-data'; file?: Blob; }", + " case 'multipart/form-data': {", + " body = formParams;"); + + // Content-Type is set per branch rather than once up front: a multipart body must not set it at all, + // fetch adds it with the boundary it generates. + String content = Files.readString(api); + int convert = content.indexOf("async convertRequestOpts"); + int convertEnd = content.indexOf("async convertRaw", convert); + String convertOpts = content.substring(convert, convertEnd); + assertThat(convertOpts).contains("headerParameters['Content-Type'] = 'application/json';"); + assertThat(convertOpts) + .as("a multipart branch must leave Content-Type to fetch") + .doesNotContain("headerParameters['Content-Type'] = 'multipart/form-data';"); + } + + @Test + public void testLeavesOperationsUntouchedWithoutTheGlobalOption() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("typescript-fetch") + .setInputSpec("src/test/resources/3_0/issue6708-split-by-content-type.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + Generator generator = new DefaultGenerator(); + generator.opts(configurator.toClientOptInput()).generate().forEach(File::deleteOnExit); + + // opt-in: without the global property nothing is split, so nothing is merged either + Path api = Paths.get(output + "/apis/ReportApi.ts"); + TestUtils.assertFileContains(api, "export interface CreateReportRequest {"); + TestUtils.assertFileNotContains(api, "contentType?: 'application/json'", "accept?: 'application/json'"); + } + @Test public void testModelsWithoutPaths() throws IOException { final String specPath = "src/test/resources/3_1/reusable-components-without-paths.yaml"; diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-enum-param.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-enum-param.yaml new file mode 100644 index 000000000000..bae400378853 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-enum-param.yaml @@ -0,0 +1,34 @@ +openapi: 3.0.1 +info: + title: enum parameter on a multi content-type operation (issue 6708) + version: 1.0.0 +paths: + /orders: + get: + operationId: getOrders + tags: [order] + parameters: + # inline enum: its generated type is named after the operation, which the merge renames + - name: orderBy + in: query + schema: + type: string + enum: [date, amount] + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/pdf: + schema: + type: string + format: binary +components: + schemas: + Order: + type: object + properties: + reference: + type: string diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-form.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-form.yaml new file mode 100644 index 000000000000..5904fa6fe0ac --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-form.yaml @@ -0,0 +1,64 @@ +openapi: 3.0.1 +info: + title: content-type split with form bodies + version: 1.0.0 +paths: + # Cas A : body multipart UNIQUE, mais deux content-types de reponse. + # L'axe requete n'est pas decoupe : seul l'axe reponse l'est. + /upload: + post: + operationId: upload + tags: [files] + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + name: + type: string + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + application/pdf: + schema: + type: string + format: binary + # Cas B : deux content-types de requete dont un multipart -> axe requete decoupe. + /convert: + post: + operationId: convert + tags: [files] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' +components: + schemas: + Receipt: + type: object + properties: + number: + type: string diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-name-collision.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-name-collision.yaml new file mode 100644 index 000000000000..23e60b8e9057 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-name-collision.yaml @@ -0,0 +1,42 @@ +openapi: 3.0.1 +info: + title: merged operation name collides with an imported model (issue 6708) + version: 1.0.0 +paths: + /reports: + post: + operationId: createReport + tags: [report] + requestBody: + content: + # the operation's request interface would be named CreateReportRequest, like this model + application/json: + schema: + $ref: '#/components/schemas/CreateReportRequest' + application/xml: + schema: + $ref: '#/components/schemas/CreateReportXmlRequest' + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Report' +components: + schemas: + CreateReportRequest: + type: object + properties: + title: + type: string + CreateReportXmlRequest: + type: object + properties: + titleXml: + type: string + Report: + type: object + properties: + id: + type: string diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-optional-response.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-optional-response.yaml new file mode 100644 index 000000000000..f64d4a49f8b4 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-optional-response.yaml @@ -0,0 +1,36 @@ +openapi: 3.0.1 +info: + title: optional response on a multi content-type operation (issue 6708) + version: 1.0.0 +paths: + /reports/{id}: + get: + operationId: getReport + tags: [report] + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/pdf: + schema: + type: string + format: binary + # a 2xx with no body: the method returns null for it instead of parsing nothing + '204': + description: not ready yet +components: + schemas: + Report: + type: object + properties: + id: + type: string diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-body.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-body.yaml new file mode 100644 index 000000000000..b541ead6687f --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-body.yaml @@ -0,0 +1,75 @@ +openapi: 3.0.1 +info: + title: solidite du discriminant + version: 1.0.0 +paths: + # body optionnel, aucun autre parametre + /reports: + post: + operationId: createReport + tags: [report] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/xml: + schema: + $ref: '#/components/schemas/ReportXml' + responses: + '200': { description: ok, content: { application/json: { schema: { $ref: '#/components/schemas/Receipt' } } } } + # meme chose, mais avec un parametre requis en plus : le membre par defaut n'est plus "weak" + /projects/{projectId}/reports: + post: + operationId: createProjectReport + tags: [report] + parameters: + - name: projectId + in: path + required: true + schema: { type: string } + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/xml: + schema: + $ref: '#/components/schemas/ReportXml' + responses: + '200': { description: ok, content: { application/json: { schema: { $ref: '#/components/schemas/Receipt' } } } } + /projects/{projectId}/drafts: + post: + operationId: createDraft + tags: [report] + parameters: + - name: projectId + in: path + required: true + schema: { type: string } + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/xml: + schema: + $ref: '#/components/schemas/ReportXml' + responses: + '200': { description: ok, content: { application/json: { schema: { $ref: '#/components/schemas/Receipt' } } } } +components: + schemas: + Report: + type: object + properties: + id: { type: string } + name: { type: string } + ReportXml: + type: object + properties: + ref: { type: string } + Receipt: + type: object + properties: + number: { type: string } diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-form.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-form.yaml new file mode 100644 index 000000000000..19eafeb5e177 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-required-form.yaml @@ -0,0 +1,38 @@ +openapi: 3.0.1 +info: + title: required form parameter on the default content-type variant (issue 6708) + version: 1.0.0 +paths: + /convert: + post: + operationId: convert + tags: [files] + requestBody: + content: + # declared first: this variant is the default one, and its `file` parameter is required - + # but only for callers who actually send multipart + multipart/form-data: + schema: + type: object + required: [file] + properties: + file: + type: string + format: binary + application/json: + schema: + $ref: '#/components/schemas/Receipt' + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' +components: + schemas: + Receipt: + type: object + properties: + reference: + type: string diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-variant-enum.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-variant-enum.yaml new file mode 100644 index 000000000000..356c620bfcf4 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-variant-enum.yaml @@ -0,0 +1,40 @@ +openapi: 3.0.1 +info: + title: inline enum on a non-default content-type variant (issue 6708) + version: 1.0.0 +paths: + /convert: + post: + operationId: convert + tags: [files] + requestBody: + content: + # declared first: this variant survives the merge, and it has no `mode` parameter + application/json: + schema: + $ref: '#/components/schemas/Receipt' + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + # inline enum: its type only exists on the dropped variant's parameters + mode: + type: string + enum: [fast, thorough] + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' +components: + schemas: + Receipt: + type: object + properties: + reference: + type: string From 78329ba92dc681b9bb58b0ded0b2545679eeb18e Mon Sep 17 00:00:00 2001 From: Antoine Date: Fri, 7 Aug 2026 18:00:43 +0200 Subject: [PATCH 09/11] Fix problem with samples of petstore in resttemplate springboot4-jackson3 --- .../petstore/java/resttemplate-springBoot4-jackson3/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/client/petstore/java/resttemplate-springBoot4-jackson3/pom.xml b/samples/client/petstore/java/resttemplate-springBoot4-jackson3/pom.xml index b5c5141bdd3d..859141904ec9 100644 --- a/samples/client/petstore/java/resttemplate-springBoot4-jackson3/pom.xml +++ b/samples/client/petstore/java/resttemplate-springBoot4-jackson3/pom.xml @@ -269,7 +269,7 @@ UTF-8 - 7.0.8 + 7.0.5 3.1.5 3.0.0 From ff11dca9ce1513686f353d8ee19fee8e0155b838 Mon Sep 17 00:00:00 2001 From: Antoine Date: Fri, 7 Aug 2026 18:55:59 +0200 Subject: [PATCH 10/11] #6708 : add a typescript-fetch sample generated with the option on Nothing committed showed what splitOperationsByContentType emits, and nothing in CI compiled it: the option was exercised only by unit tests asserting on strings in a temp directory. Reviewers had to build the branch to see the feature, and a regression that produced uncompilable TypeScript would have gone unnoticed - the review of this branch found four of those. The sample's spec gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body whose operation is split on the response axis only, a request split mixing JSON and multipart, and an enum parameter carried by a split operation. bin/ts-typecheck-all.sh discovers samples on its own - any generated directory holding both a tsconfig.json and a package.json is typechecked - so setting npmName is all it takes for CI to compile this one. No workflow change needed. Writing the sample immediately paid for itself: the form body assembled inside the content-type switch was under-indented by eight columns. IndentedLambda leaves the first line alone, and moving the partial to column zero in the previous commit removed the literal spaces that used to indent it. --- ...ypescript-fetch-split-by-content-type.yaml | 10 + .../apisContentTypeVariantBody.mustache | 3 +- ...ssue6708-split-by-content-type-sample.yaml | 155 ++++++ .../builds/split-by-content-type/.gitignore | 4 + .../builds/split-by-content-type/.npmignore | 1 + .../.openapi-generator-ignore | 23 + .../.openapi-generator/FILES | 24 + .../.openapi-generator/VERSION | 1 + .../builds/split-by-content-type/README.md | 119 +++++ .../split-by-content-type/docs/FilesApi.md | 143 ++++++ .../split-by-content-type/docs/Order.md | 34 ++ .../split-by-content-type/docs/OrderApi.md | 74 +++ .../split-by-content-type/docs/Receipt.md | 34 ++ .../split-by-content-type/docs/Report.md | 36 ++ .../split-by-content-type/docs/ReportApi.md | 140 ++++++ .../split-by-content-type/docs/ReportXml.md | 34 ++ .../builds/split-by-content-type/package.json | 21 + .../src/apis/FilesApi.ts | 176 +++++++ .../src/apis/OrderApi.ts | 90 ++++ .../src/apis/ReportApi.ts | 160 ++++++ .../split-by-content-type/src/apis/index.ts | 5 + .../builds/split-by-content-type/src/index.ts | 5 + .../split-by-content-type/src/models/Order.ts | 63 +++ .../src/models/Receipt.ts | 63 +++ .../src/models/Report.ts | 69 +++ .../src/models/ReportXml.ts | 63 +++ .../split-by-content-type/src/models/index.ts | 6 + .../split-by-content-type/src/runtime.ts | 467 ++++++++++++++++++ .../split-by-content-type/tsconfig.esm.json | 7 + .../split-by-content-type/tsconfig.json | 16 + 30 files changed, 2045 insertions(+), 1 deletion(-) create mode 100644 bin/configs/typescript-fetch-split-by-content-type.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/.gitignore create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/.npmignore create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator-ignore create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/VERSION create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Order.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Receipt.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Report.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/package.json create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/index.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/index.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.esm.json create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.json diff --git a/bin/configs/typescript-fetch-split-by-content-type.yaml b/bin/configs/typescript-fetch-split-by-content-type.yaml new file mode 100644 index 000000000000..e05eb6900874 --- /dev/null +++ b/bin/configs/typescript-fetch-split-by-content-type.yaml @@ -0,0 +1,10 @@ +generatorName: typescript-fetch +outputDir: samples/client/petstore/typescript-fetch/builds/split-by-content-type +inputSpec: modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml +templateDir: modules/openapi-generator/src/main/resources/typescript-fetch +globalProperties: + splitOperationsByContentType: "true" +additionalProperties: + npmVersion: 1.0.0 + npmName: '@openapitools/typescript-fetch-split-by-content-type' + snapshot: false diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache index 8c47b80c237e..4b5e57bfaf22 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apisContentTypeVariantBody.mustache @@ -13,7 +13,8 @@ } {{/required}} {{/formParams}} -{{#lambda.indented_8_skip_blank}}{{>apisFormParams}}{{/lambda.indented_8_skip_blank}} +{{! the lambda leaves the first line alone, so the literal spaces below are what indent it }} + {{#lambda.indented_8_skip_blank}}{{>apisFormParams}}{{/lambda.indented_8_skip_blank}} {{! a multipart body sets no Content-Type: fetch adds it with the boundary it generates }} body = formParams; {{/hasFormParams}} diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml new file mode 100644 index 000000000000..01a42d7f8c2d --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml @@ -0,0 +1,155 @@ +openapi: 3.0.1 +info: + title: split operations by content-type (issue 6708) + description: > + Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the + option has to handle: a response-only split, a split on both axes, a multipart body, a request + split that mixes JSON and multipart, and an enum parameter carried by a split operation. + version: 1.0.0 +paths: + # Response axis only: the request body is untouched, `accept` selects the return type. + /reports/{id}: + get: + operationId: getReport + tags: [report] + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/directlog: + schema: + type: string + format: binary + # Both axes: `contentType` selects the body's type, `accept` the return type. + /reports: + post: + operationId: createReport + tags: [report] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Report' + application/xml: + schema: + $ref: '#/components/schemas/ReportXml' + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + application/pdf: + schema: + type: string + format: binary + # A single multipart body, two response content-types: only the response axis is split, and the + # form body is still assembled the way an unsplit operation assembles it. + /upload: + post: + operationId: upload + tags: [files] + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + name: + type: string + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + application/pdf: + schema: + type: string + format: binary + # Request split where one member is multipart: the form body is assembled inside the + # content-type switch, where the request union is narrowed to that member. + /convert: + post: + operationId: convert + tags: [files] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Receipt' + # Inline enum parameter: its generated type is named after the operation, so the merge has to + # move it onto the merged name rather than leave it on a variant nobody declares. + /orders: + get: + operationId: getOrders + tags: [order] + parameters: + - name: orderBy + in: query + schema: + type: string + enum: [date, amount] + responses: + '200': + description: ok + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + application/pdf: + schema: + type: string + format: binary +components: + schemas: + Report: + type: object + properties: + id: + type: string + name: + type: string + ReportXml: + type: object + properties: + ref: + type: string + Receipt: + type: object + properties: + number: + type: string + Order: + type: object + properties: + reference: + type: string diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.gitignore b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.gitignore new file mode 100644 index 000000000000..149b57654723 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.npmignore b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.npmignore new file mode 100644 index 000000000000..42061c01a1c7 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.npmignore @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator-ignore b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.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-fetch/builds/split-by-content-type/.openapi-generator/FILES b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES new file mode 100644 index 000000000000..f78f9a9f7f4a --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES @@ -0,0 +1,24 @@ +.gitignore +.npmignore +README.md +docs/FilesApi.md +docs/Order.md +docs/OrderApi.md +docs/Receipt.md +docs/Report.md +docs/ReportApi.md +docs/ReportXml.md +package.json +src/apis/FilesApi.ts +src/apis/OrderApi.ts +src/apis/ReportApi.ts +src/apis/index.ts +src/index.ts +src/models/Order.ts +src/models/Receipt.ts +src/models/Report.ts +src/models/ReportXml.ts +src/models/index.ts +src/runtime.ts +tsconfig.esm.json +tsconfig.json diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/VERSION b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/VERSION new file mode 100644 index 000000000000..8fc8df61083a --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.25.0-SNAPSHOT diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md new file mode 100644 index 000000000000..c9a3225a49ea --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md @@ -0,0 +1,119 @@ +# @openapitools/typescript-fetch-split-by-content-type@1.0.0 + +A TypeScript SDK client for the localhost API. + +## Usage + +First, install the SDK from npm. + +```bash +npm install @openapitools/typescript-fetch-split-by-content-type --save +``` + +Next, try it out. + + +```ts +import { + Configuration, + FilesApi, +} from '@openapitools/typescript-fetch-split-by-content-type'; +import type { ConvertRequest } from '@openapitools/typescript-fetch-split-by-content-type'; + +async function example() { + console.log("🚀 Testing @openapitools/typescript-fetch-split-by-content-type SDK..."); + const api = new FilesApi(); + + const body = { + // Receipt (optional) + receipt: ..., + } satisfies ConvertRequest; + + try { + const data = await api.convert(body); + console.log(data); + } catch (error) { + console.error(error); + } +} + +// Run the test +example().catch(console.error); +``` + + +## Documentation + +### API Endpoints + +All URIs are relative to *http://localhost* + +| Class | Method | HTTP request | Description +| ----- | ------ | ------------ | ------------- +*FilesApi* | [**convert**](docs/FilesApi.md#convert) | **POST** /convert | +*FilesApi* | [**upload**](docs/FilesApi.md#upload) | **POST** /upload | +*OrderApi* | [**getOrders**](docs/OrderApi.md#getorders) | **GET** /orders | +*ReportApi* | [**createReport**](docs/ReportApi.md#createreport) | **POST** /reports | +*ReportApi* | [**getReport**](docs/ReportApi.md#getreport) | **GET** /reports/{id} | + + +### Models + +- [Order](docs/Order.md) +- [Receipt](docs/Receipt.md) +- [Report](docs/Report.md) +- [ReportXml](docs/ReportXml.md) + +### Authorization + +Endpoints do not require authorization. + + +## About + +This TypeScript SDK client supports the [Fetch API](https://fetch.spec.whatwg.org/) +and is automatically generated by the +[OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: `1.0.0` +- Package version: `1.0.0` +- Generator version: `7.25.0-SNAPSHOT` +- Build package: `org.openapitools.codegen.languages.TypeScriptFetchClientCodegen` + +The generated npm module supports the following: + +- Environments + * Node.js + * Webpack + * Browserify +- Language levels + * ES5 - you must have a Promises/A+ library installed + * ES6 +- Module systems + * CommonJS + * ES6 module system + + +## Development + +### Building + +To build the TypeScript source code, you need to have Node.js and npm installed. +After cloning the repository, navigate to the project directory and run: + +```bash +npm install +npm run build +``` + +### Publishing + +Once you've built the package, you can publish it to npm: + +```bash +npm publish +``` + +## License + +[]() diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md new file mode 100644 index 000000000000..06984876acd4 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md @@ -0,0 +1,143 @@ +# FilesApi + +All URIs are relative to *http://localhost* + +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +| [**convert**](FilesApi.md#convert) | **POST** /convert | | +| [**upload**](FilesApi.md#upload) | **POST** /upload | | + + + +## convert + +> Receipt convert(receipt) + + + +### Example + +```ts +import { + Configuration, + FilesApi, +} from '@openapitools/typescript-fetch-split-by-content-type'; +import type { ConvertRequest } from '@openapitools/typescript-fetch-split-by-content-type'; + +async function example() { + console.log("🚀 Testing @openapitools/typescript-fetch-split-by-content-type SDK..."); + const api = new FilesApi(); + + const body = { + // Receipt (optional) + receipt: ..., + } satisfies ConvertRequest; + + try { + const data = await api.convert(body); + console.log(data); + } catch (error) { + console.error(error); + } +} + +// Run the test +example().catch(console.error); +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **receipt** | [Receipt](Receipt.md) | | [Optional] | + +### Return type + +[**Receipt**](Receipt.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: `application/json` +- **Accept**: `application/json` + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | ok | - | + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + + +## upload + +> Receipt upload(file, name) + + + +### Example + +```ts +import { + Configuration, + FilesApi, +} from '@openapitools/typescript-fetch-split-by-content-type'; +import type { UploadRequest } from '@openapitools/typescript-fetch-split-by-content-type'; + +async function example() { + console.log("🚀 Testing @openapitools/typescript-fetch-split-by-content-type SDK..."); + const api = new FilesApi(); + + const body = { + // Blob (optional) + file: BINARY_DATA_HERE, + // string (optional) + name: name_example, + } satisfies UploadRequest; + + try { + const data = await api.upload(body); + console.log(data); + } catch (error) { + console.error(error); + } +} + +// Run the test +example().catch(console.error); +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **file** | `Blob` | | [Optional] [Defaults to `undefined`] | +| **name** | `string` | | [Optional] [Defaults to `undefined`] | + +### Return type + +[**Receipt**](Receipt.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: `multipart/form-data` +- **Accept**: `application/json` + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | ok | - | + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Order.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Order.md new file mode 100644 index 000000000000..82efb7a4be8a --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Order.md @@ -0,0 +1,34 @@ + +# Order + + +## Properties + +Name | Type +------------ | ------------- +`reference` | string + +## Example + +```typescript +import type { Order } from '@openapitools/typescript-fetch-split-by-content-type' + +// TODO: Update the object below with actual values +const example = { + "reference": null, +} satisfies Order + +console.log(example) + +// Convert the instance to a JSON string +const exampleJSON: string = JSON.stringify(example) +console.log(exampleJSON) + +// Parse the JSON string back to an object +const exampleParsed = JSON.parse(exampleJSON) as Order +console.log(exampleParsed) +``` + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md new file mode 100644 index 000000000000..813f0f289689 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md @@ -0,0 +1,74 @@ +# OrderApi + +All URIs are relative to *http://localhost* + +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +| [**getOrders**](OrderApi.md#getorders) | **GET** /orders | | + + + +## getOrders + +> Order getOrders(orderBy) + + + +### Example + +```ts +import { + Configuration, + OrderApi, +} from '@openapitools/typescript-fetch-split-by-content-type'; +import type { GetOrdersRequest } from '@openapitools/typescript-fetch-split-by-content-type'; + +async function example() { + console.log("🚀 Testing @openapitools/typescript-fetch-split-by-content-type SDK..."); + const api = new OrderApi(); + + const body = { + // 'date' | 'amount' (optional) + orderBy: orderBy_example, + } satisfies GetOrdersRequest; + + try { + const data = await api.getOrders(body); + console.log(data); + } catch (error) { + console.error(error); + } +} + +// Run the test +example().catch(console.error); +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **orderBy** | `date`, `amount` | | [Optional] [Defaults to `undefined`] [Enum: date, amount] | + +### Return type + +[**Order**](Order.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: `application/json` + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | ok | - | + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Receipt.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Receipt.md new file mode 100644 index 000000000000..a154c4bacb59 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Receipt.md @@ -0,0 +1,34 @@ + +# Receipt + + +## Properties + +Name | Type +------------ | ------------- +`number` | string + +## Example + +```typescript +import type { Receipt } from '@openapitools/typescript-fetch-split-by-content-type' + +// TODO: Update the object below with actual values +const example = { + "number": null, +} satisfies Receipt + +console.log(example) + +// Convert the instance to a JSON string +const exampleJSON: string = JSON.stringify(example) +console.log(exampleJSON) + +// Parse the JSON string back to an object +const exampleParsed = JSON.parse(exampleJSON) as Receipt +console.log(exampleParsed) +``` + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Report.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Report.md new file mode 100644 index 000000000000..486e4628c6cc --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/Report.md @@ -0,0 +1,36 @@ + +# Report + + +## Properties + +Name | Type +------------ | ------------- +`id` | string +`name` | string + +## Example + +```typescript +import type { Report } from '@openapitools/typescript-fetch-split-by-content-type' + +// TODO: Update the object below with actual values +const example = { + "id": null, + "name": null, +} satisfies Report + +console.log(example) + +// Convert the instance to a JSON string +const exampleJSON: string = JSON.stringify(example) +console.log(exampleJSON) + +// Parse the JSON string back to an object +const exampleParsed = JSON.parse(exampleJSON) as Report +console.log(exampleParsed) +``` + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md new file mode 100644 index 000000000000..13ad8bb1ce77 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md @@ -0,0 +1,140 @@ +# ReportApi + +All URIs are relative to *http://localhost* + +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +| [**createReport**](ReportApi.md#createreport) | **POST** /reports | | +| [**getReport**](ReportApi.md#getreport) | **GET** /reports/{id} | | + + + +## createReport + +> Receipt createReport(report) + + + +### Example + +```ts +import { + Configuration, + ReportApi, +} from '@openapitools/typescript-fetch-split-by-content-type'; +import type { CreateReportRequest } from '@openapitools/typescript-fetch-split-by-content-type'; + +async function example() { + console.log("🚀 Testing @openapitools/typescript-fetch-split-by-content-type SDK..."); + const api = new ReportApi(); + + const body = { + // Report (optional) + report: ..., + } satisfies CreateReportRequest; + + try { + const data = await api.createReport(body); + console.log(data); + } catch (error) { + console.error(error); + } +} + +// Run the test +example().catch(console.error); +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **report** | [Report](Report.md) | | [Optional] | + +### Return type + +[**Receipt**](Receipt.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: `application/json` +- **Accept**: `application/json` + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | ok | - | + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + + +## getReport + +> Report getReport(id) + + + +### Example + +```ts +import { + Configuration, + ReportApi, +} from '@openapitools/typescript-fetch-split-by-content-type'; +import type { GetReportRequest } from '@openapitools/typescript-fetch-split-by-content-type'; + +async function example() { + console.log("🚀 Testing @openapitools/typescript-fetch-split-by-content-type SDK..."); + const api = new ReportApi(); + + const body = { + // string + id: id_example, + } satisfies GetReportRequest; + + try { + const data = await api.getReport(body); + console.log(data); + } catch (error) { + console.error(error); + } +} + +// Run the test +example().catch(console.error); +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **id** | `string` | | [Defaults to `undefined`] | + +### Return type + +[**Report**](Report.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: `application/json` + + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | ok | - | + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md new file mode 100644 index 000000000000..2d1b34fa4d5f --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md @@ -0,0 +1,34 @@ + +# ReportXml + + +## Properties + +Name | Type +------------ | ------------- +`ref` | string + +## Example + +```typescript +import type { ReportXml } from '@openapitools/typescript-fetch-split-by-content-type' + +// TODO: Update the object below with actual values +const example = { + "ref": null, +} satisfies ReportXml + +console.log(example) + +// Convert the instance to a JSON string +const exampleJSON: string = JSON.stringify(example) +console.log(exampleJSON) + +// Parse the JSON string back to an object +const exampleParsed = JSON.parse(exampleJSON) as ReportXml +console.log(exampleParsed) +``` + +[[Back to top]](#) [[Back to API list]](../README.md#api-endpoints) [[Back to Model list]](../README.md#models) [[Back to README]](../README.md) + + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/package.json b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/package.json new file mode 100644 index 000000000000..80640b18336f --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/package.json @@ -0,0 +1,21 @@ +{ + "name": "@openapitools/typescript-fetch-split-by-content-type", + "version": "1.0.0", + "description": "OpenAPI client for @openapitools/typescript-fetch-split-by-content-type", + "author": "OpenAPI-Generator", + "repository": { + "type": "git", + "url": "https://github.com/GIT_USER_ID/GIT_REPO_ID.git" + }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "module": "./dist/esm/index.js", + "sideEffects": false, + "scripts": { + "build": "tsc && tsc -p tsconfig.esm.json", + "prepare": "npm run build" + }, + "devDependencies": { + "typescript": "^4.0 || ^5.0" + } +} diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts new file mode 100644 index 000000000000..1cc17b729765 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts @@ -0,0 +1,176 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 * as runtime from '../runtime'; +import { + type Receipt, + ReceiptFromJSON, + ReceiptToJSON, +} from '../models/Receipt'; + +export type ConvertRequest = runtime.ExclusiveUnion< + | { contentType?: 'application/json'; receipt?: Receipt; } + | { contentType: 'multipart/form-data'; file?: Blob; } +>; + +export type UploadRequest = + | { file?: Blob; name?: string; } +; + +/** + * + */ +export class FilesApi extends runtime.BaseAPI { + + /** + * Creates request options for convert without sending the request + */ + async convertRequestOpts(requestParameters: ConvertRequest): Promise { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + + let urlPath = `/convert`; + + let body: any; + switch (requestParameters.contentType) { + case 'multipart/form-data': { + const consumes: runtime.Consume[] = [ + { contentType: 'multipart/form-data' }, + ]; + // @ts-ignore: canConsumeForm may be unused + const canConsumeForm = runtime.canConsumeForm(consumes); + + let formParams: { append(param: string, value: any): any }; + let useForm = false; + // use FormData to transmit files using content-type "multipart/form-data" + useForm = canConsumeForm; + if (useForm) { + formParams = new FormData(); + } else { + formParams = new URLSearchParams(); + } + + if (requestParameters['file'] != null) { + formParams.append('file', requestParameters['file'] as any); + } + + + body = formParams; + break; + } + default: { + headerParameters['Content-Type'] = 'application/json'; + body = ReceiptToJSON(requestParameters['receipt']); + } + } + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: body, + }; + } + + /** + */ + async convertRaw(requestParameters: ConvertRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.convertRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => ReceiptFromJSON(jsonValue)); + } + + /** + */ + async convert(requestParameters: ConvertRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.convertRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for upload without sending the request + */ + async uploadRequestOpts(requestParameters: UploadRequest & { accept?: string }): Promise { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Accept'] = requestParameters.accept ?? 'application/json'; + + const consumes: runtime.Consume[] = [ + { contentType: 'multipart/form-data' }, + ]; + // @ts-ignore: canConsumeForm may be unused + const canConsumeForm = runtime.canConsumeForm(consumes); + + let formParams: { append(param: string, value: any): any }; + let useForm = false; + // use FormData to transmit files using content-type "multipart/form-data" + useForm = canConsumeForm; + if (useForm) { + formParams = new FormData(); + } else { + formParams = new URLSearchParams(); + } + + if (requestParameters['file'] != null) { + formParams.append('file', requestParameters['file'] as any); + } + + if (requestParameters['name'] != null) { + formParams.append('name', requestParameters['name'] as any); + } + + + let urlPath = `/upload`; + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: formParams, + }; + } + + /** + */ + async uploadRaw(requestParameters: UploadRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async uploadRaw(requestParameters: UploadRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async uploadRaw(requestParameters: UploadRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.uploadRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + if (responseContentType === 'application/pdf') { + return new runtime.BlobApiResponse(response) as any; + } else { + return new runtime.JSONApiResponse(response, (jsonValue) => ReceiptFromJSON(jsonValue)) as any; + } + } + + /** + */ + async upload(requestParameters: UploadRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async upload(requestParameters: UploadRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async upload(requestParameters: UploadRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.uploadRaw(requestParameters as any, initOverrides); + return await response.value(); + } + +} diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts new file mode 100644 index 000000000000..885906a5195f --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts @@ -0,0 +1,90 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 * as runtime from '../runtime'; +import { + type Order, + OrderFromJSON, + OrderToJSON, +} from '../models/Order'; + +export type GetOrdersRequest = + | { orderBy?: GetOrdersOrderByEnum; } +; + +/** + * + */ +export class OrderApi extends runtime.BaseAPI { + + /** + * Creates request options for getOrders without sending the request + */ + async getOrdersRequestOpts(requestParameters: GetOrdersRequest & { accept?: string }): Promise { + const queryParameters: any = {}; + + if (requestParameters['orderBy'] != null) { + queryParameters['orderBy'] = requestParameters['orderBy']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Accept'] = requestParameters.accept ?? 'application/json'; + + + let urlPath = `/orders`; + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + */ + async getOrdersRaw(requestParameters: GetOrdersRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async getOrdersRaw(requestParameters: GetOrdersRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async getOrdersRaw(requestParameters: GetOrdersRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrdersRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + if (responseContentType === 'application/pdf') { + return new runtime.BlobApiResponse(response) as any; + } else { + return new runtime.JSONApiResponse(response, (jsonValue) => OrderFromJSON(jsonValue)) as any; + } + } + + /** + */ + async getOrders(requestParameters: GetOrdersRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async getOrders(requestParameters: GetOrdersRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async getOrders(requestParameters: GetOrdersRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getOrdersRaw(requestParameters as any, initOverrides); + return await response.value(); + } + +} + +/** + * @export + */ +export const GetOrdersOrderByEnum = { + Date: 'date', + Amount: 'amount' +} as const; +export type GetOrdersOrderByEnum = typeof GetOrdersOrderByEnum[keyof typeof GetOrdersOrderByEnum]; diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts new file mode 100644 index 000000000000..fecd290d0d24 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts @@ -0,0 +1,160 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 * as runtime from '../runtime'; +import { + type Receipt, + ReceiptFromJSON, + ReceiptToJSON, +} from '../models/Receipt'; +import { + type Report, + ReportFromJSON, + ReportToJSON, +} from '../models/Report'; +import { + type ReportXml, + ReportXmlFromJSON, + ReportXmlToJSON, +} from '../models/ReportXml'; + +export type CreateReportRequest = runtime.ExclusiveUnion< + | { contentType?: 'application/json'; report?: Report; } + | { contentType: 'application/xml'; reportXml?: ReportXml; } +>; + +export type GetReportRequest = + | { id: string; } +; + +/** + * + */ +export class ReportApi extends runtime.BaseAPI { + + /** + * Creates request options for createReport without sending the request + */ + async createReportRequestOpts(requestParameters: CreateReportRequest & { accept?: string }): Promise { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Accept'] = requestParameters.accept ?? 'application/json'; + + + let urlPath = `/reports`; + + let body: any; + switch (requestParameters.contentType) { + case 'application/xml': { + headerParameters['Content-Type'] = 'application/xml'; + body = ReportXmlToJSON(requestParameters['reportXml']); + break; + } + default: { + headerParameters['Content-Type'] = 'application/json'; + body = ReportToJSON(requestParameters['report']); + } + } + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: body, + }; + } + + /** + */ + async createReportRaw(requestParameters: CreateReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async createReportRaw(requestParameters: CreateReportRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async createReportRaw(requestParameters: CreateReportRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createReportRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + if (responseContentType === 'application/pdf') { + return new runtime.BlobApiResponse(response) as any; + } else { + return new runtime.JSONApiResponse(response, (jsonValue) => ReceiptFromJSON(jsonValue)) as any; + } + } + + /** + */ + async createReport(requestParameters: CreateReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async createReport(requestParameters: CreateReportRequest & { accept: 'application/pdf' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async createReport(requestParameters: CreateReportRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.createReportRaw(requestParameters as any, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getReport without sending the request + */ + async getReportRequestOpts(requestParameters: GetReportRequest & { accept?: string }): Promise { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling getReport().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Accept'] = requestParameters.accept ?? 'application/json'; + + + let urlPath = `/reports/{id}`; + urlPath = urlPath.replace('{id}', encodeURIComponent(String(requestParameters['id']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + */ + async getReportRaw(requestParameters: GetReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async getReportRaw(requestParameters: GetReportRequest & { accept: 'application/directlog' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>; + async getReportRaw(requestParameters: GetReportRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getReportRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + if (responseContentType === 'application/directlog') { + return new runtime.BlobApiResponse(response) as any; + } else { + return new runtime.JSONApiResponse(response, (jsonValue) => ReportFromJSON(jsonValue)) as any; + } + } + + /** + */ + async getReport(requestParameters: GetReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async getReport(requestParameters: GetReportRequest & { accept: 'application/directlog' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; + async getReport(requestParameters: GetReportRequest & { accept?: string }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getReportRaw(requestParameters as any, initOverrides); + return await response.value(); + } + +} diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/index.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/index.ts new file mode 100644 index 000000000000..b374c4d14a91 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/index.ts @@ -0,0 +1,5 @@ +/* tslint:disable */ +/* eslint-disable */ +export * from './FilesApi'; +export * from './OrderApi'; +export * from './ReportApi'; diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/index.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/index.ts new file mode 100644 index 000000000000..bebe8bbbe206 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/index.ts @@ -0,0 +1,5 @@ +/* tslint:disable */ +/* eslint-disable */ +export * from './runtime'; +export * from './apis/index'; +export * from './models/index'; diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts new file mode 100644 index 000000000000..804d08ea297f --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 { mapValues } from '../runtime'; +/** + * + * @export + * @interface Order + */ +export interface Order { + /** + * + */ + reference?: string; +} + +/** + * Check if a given object implements the Order interface. + */ +export function instanceOfOrder(value: object): value is Order { + return true; +} + +export function OrderFromJSON(json: any): Order { + return OrderFromJSONTyped(json, false); +} + +export function OrderFromJSONTyped(json: any, ignoreDiscriminator: boolean): Order { + if (json == null) { + return json; + } + return { + + 'reference': json['reference'] == null ? undefined : json['reference'], + }; +} + +export function OrderToJSON(json: any): Order { + return OrderToJSONTyped(json, false); +} + +export function OrderToJSONTyped(value?: Order | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'reference': value['reference'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts new file mode 100644 index 000000000000..0180387291e3 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 { mapValues } from '../runtime'; +/** + * + * @export + * @interface Receipt + */ +export interface Receipt { + /** + * + */ + number?: string; +} + +/** + * Check if a given object implements the Receipt interface. + */ +export function instanceOfReceipt(value: object): value is Receipt { + return true; +} + +export function ReceiptFromJSON(json: any): Receipt { + return ReceiptFromJSONTyped(json, false); +} + +export function ReceiptFromJSONTyped(json: any, ignoreDiscriminator: boolean): Receipt { + if (json == null) { + return json; + } + return { + + 'number': json['number'] == null ? undefined : json['number'], + }; +} + +export function ReceiptToJSON(json: any): Receipt { + return ReceiptToJSONTyped(json, false); +} + +export function ReceiptToJSONTyped(value?: Receipt | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'number': value['number'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts new file mode 100644 index 000000000000..e03f85f768d7 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 { mapValues } from '../runtime'; +/** + * + * @export + * @interface Report + */ +export interface Report { + /** + * + */ + id?: string; + /** + * + */ + name?: string; +} + +/** + * Check if a given object implements the Report interface. + */ +export function instanceOfReport(value: object): value is Report { + return true; +} + +export function ReportFromJSON(json: any): Report { + return ReportFromJSONTyped(json, false); +} + +export function ReportFromJSONTyped(json: any, ignoreDiscriminator: boolean): Report { + if (json == null) { + return json; + } + return { + + 'id': json['id'] == null ? undefined : json['id'], + 'name': json['name'] == null ? undefined : json['name'], + }; +} + +export function ReportToJSON(json: any): Report { + return ReportToJSONTyped(json, false); +} + +export function ReportToJSONTyped(value?: Report | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'id': value['id'], + 'name': value['name'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts new file mode 100644 index 000000000000..c4292c5f4002 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 { mapValues } from '../runtime'; +/** + * + * @export + * @interface ReportXml + */ +export interface ReportXml { + /** + * + */ + ref?: string; +} + +/** + * Check if a given object implements the ReportXml interface. + */ +export function instanceOfReportXml(value: object): value is ReportXml { + return true; +} + +export function ReportXmlFromJSON(json: any): ReportXml { + return ReportXmlFromJSONTyped(json, false); +} + +export function ReportXmlFromJSONTyped(json: any, ignoreDiscriminator: boolean): ReportXml { + if (json == null) { + return json; + } + return { + + 'ref': json['ref'] == null ? undefined : json['ref'], + }; +} + +export function ReportXmlToJSON(json: any): ReportXml { + return ReportXmlToJSONTyped(json, false); +} + +export function ReportXmlToJSONTyped(value?: ReportXml | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'ref': value['ref'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts new file mode 100644 index 000000000000..f0a53f5591aa --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts @@ -0,0 +1,6 @@ +/* tslint:disable */ +/* eslint-disable */ +export * from './Order'; +export * from './Receipt'; +export * from './Report'; +export * from './ReportXml'; diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts new file mode 100644 index 000000000000..af99999f0167 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts @@ -0,0 +1,467 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * + * 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 const BASE_PATH = "http://localhost".replace(/\/+$/, ""); + +export interface ConfigurationParameters { + basePath?: string; // override base path + fetchApi?: FetchAPI; // override for fetch implementation + middleware?: Middleware[]; // middleware to apply before/after fetch requests + queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings + username?: string; // parameter for basic security + password?: string; // parameter for basic security + apiKey?: string | Promise | ((name: string) => string | Promise); // parameter for apiKey security + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security + headers?: HTTPHeaders; //header params we want to use on every request + credentials?: RequestCredentials; //value for the credentials param we want to use on each request +} + +export class Configuration { + constructor(private configuration: ConfigurationParameters = {}) {} + + set config(configuration: Configuration) { + this.configuration = configuration; + } + + get basePath(): string { + return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH; + } + + get fetchApi(): FetchAPI | undefined { + return this.configuration.fetchApi; + } + + get middleware(): Middleware[] { + return this.configuration.middleware || []; + } + + get queryParamsStringify(): (params: HTTPQuery) => string { + return this.configuration.queryParamsStringify || querystring; + } + + get username(): string | undefined { + return this.configuration.username; + } + + get password(): string | undefined { + return this.configuration.password; + } + + get apiKey(): ((name: string) => string | Promise) | undefined { + const apiKey = this.configuration.apiKey; + if (apiKey) { + return typeof apiKey === 'function' ? apiKey : () => apiKey; + } + return undefined; + } + + get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined { + const accessToken = this.configuration.accessToken; + if (accessToken) { + return typeof accessToken === 'function' ? accessToken : async () => accessToken; + } + return undefined; + } + + get headers(): HTTPHeaders | undefined { + return this.configuration.headers; + } + + get credentials(): RequestCredentials | undefined { + return this.configuration.credentials; + } +} + +export const DefaultConfig = new Configuration(); + +/** + * This is the base class for all generated API classes. + */ +export class BaseAPI { + + private static readonly jsonRegex = /^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$/i; + private middleware: Middleware[]; + + constructor(protected configuration = DefaultConfig) { + this.middleware = configuration.middleware; + } + + withMiddleware(this: T, ...middlewares: Middleware[]) { + const next = this.clone(); + next.middleware = next.middleware.concat(...middlewares); + return next; + } + + withPreMiddleware(this: T, ...preMiddlewares: Array) { + const middlewares = preMiddlewares.map((pre) => ({ pre })); + return this.withMiddleware(...middlewares); + } + + withPostMiddleware(this: T, ...postMiddlewares: Array) { + const middlewares = postMiddlewares.map((post) => ({ post })); + return this.withMiddleware(...middlewares); + } + + /** + * 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. + */ + protected isJsonMime(mime: string | null | undefined): boolean { + if (!mime) { + return false; + } + return BaseAPI.jsonRegex.test(mime); + } + + protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise { + const { url, init } = await this.createFetchParams(context, initOverrides); + const response = await this.fetchApi(url, init); + if (response && (response.status >= 200 && response.status < 300)) { + return response; + } + throw new ResponseError(response, 'Response returned an error code'); + } + + private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) { + let url = this.configuration.basePath + context.path; + if (context.query !== undefined && Object.keys(context.query).length !== 0) { + // 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. + url += '?' + this.configuration.queryParamsStringify(context.query); + } + + const headers = Object.assign({}, this.configuration.headers, context.headers); + Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {}); + + const initOverrideFn = + typeof initOverrides === "function" + ? initOverrides + : async () => initOverrides; + + const initParams = { + method: context.method, + headers, + body: context.body, + credentials: this.configuration.credentials, + }; + + const overriddenInit: RequestInit = { + ...initParams, + ...(await initOverrideFn({ + init: initParams, + context, + })) + }; + + let body: any; + if (isFormData(overriddenInit.body) + || (overriddenInit.body instanceof URLSearchParams) + || isBlob(overriddenInit.body)) { + body = overriddenInit.body; + } else if (this.isJsonMime(headers['Content-Type'])) { + body = JSON.stringify(overriddenInit.body); + } else { + body = overriddenInit.body; + } + + const init: RequestInit = { + ...overriddenInit, + body + }; + + return { url, init }; + } + + private fetchApi = async (url: string, init: RequestInit) => { + let fetchParams = { url, init }; + for (const middleware of this.middleware) { + if (middleware.pre) { + fetchParams = await middleware.pre({ + fetch: this.fetchApi, + ...fetchParams, + }) || fetchParams; + } + } + let response: Response | undefined = undefined; + try { + response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init); + } catch (e) { + for (const middleware of this.middleware) { + if (middleware.onError) { + response = await middleware.onError({ + fetch: this.fetchApi, + url: fetchParams.url, + init: fetchParams.init, + error: e, + response: response ? response.clone() : undefined, + }) || response; + } + } + if (response === undefined) { + if (e instanceof Error) { + throw new FetchError(e, 'The request failed and the interceptors did not return an alternative response'); + } else { + throw e; + } + } + } + for (const middleware of this.middleware) { + if (middleware.post) { + response = await middleware.post({ + fetch: this.fetchApi, + url: fetchParams.url, + init: fetchParams.init, + response: response.clone(), + }) || response; + } + } + return response; + } + + /** + * Create a shallow clone of `this` by constructing a new instance + * and then shallow cloning data members. + */ + private clone(this: T): T { + const constructor = this.constructor as any; + const next = new constructor(this.configuration); + next.middleware = this.middleware.slice(); + return next; + } +}; + +function isBlob(value: any): value is Blob { + return typeof Blob !== 'undefined' && value instanceof Blob; +} + +function isFormData(value: any): value is FormData { + return typeof FormData !== "undefined" && value instanceof FormData; +} + +export class ResponseError extends Error { + override name: "ResponseError" = "ResponseError"; + constructor(public response: Response, msg?: string) { + super(msg); + + // restore prototype chain + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } + } +} + +export class FetchError extends Error { + override name: "FetchError" = "FetchError"; + constructor(public cause: Error, msg?: string) { + super(msg); + + // restore prototype chain + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } + } +} + +export class RequiredError extends Error { + override name: "RequiredError" = "RequiredError"; + constructor(public field: string, msg?: string) { + super(msg); + + // restore prototype chain + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } + } +} + +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +export type FetchAPI = WindowOrWorkerGlobalScope['fetch']; + +type AllKeys = T extends unknown ? keyof T : never; +/** + * Makes the members of a union mutually exclusive, by declaring on each of them the keys it does not have + * as `never`. Without it a member is satisfied by a value carrying another member's keys: assignability is + * structural and tolerates surplus properties, and excess property checking never fires against a union + * since a key present in any member counts as known. + * + * `U` distributes while `T` stays the whole union, which is what lets each member see the others' keys. + */ +export type ExclusiveUnion = U extends unknown + ? U & Partial, keyof U>, never>> + : never; + +export type Json = any; +export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; +export type HTTPHeaders = { [key: string]: string }; +export type HTTPQuery = { [key: string]: string | number | null | boolean | Array | Set | HTTPQuery }; +export type HTTPBody = Json | FormData | URLSearchParams; +export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody }; +export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original'; + +export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise + +export interface FetchParams { + url: string; + init: RequestInit; +} + +export interface RequestOpts { + path: string; + method: HTTPMethod; + headers: HTTPHeaders; + query?: HTTPQuery; + body?: HTTPBody; +} + +export function querystring(params: HTTPQuery, prefix: string = ''): string { + return Object.keys(params) + .map(key => querystringSingleKey(key, params[key], prefix)) + .filter(part => part.length > 0) + .join('&'); +} + +function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array | Set | HTTPQuery, keyPrefix: string = ''): string { + const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key); + if (value instanceof Array) { + const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue))) + .join(`&${encodeURIComponent(fullKey)}=`); + return `${encodeURIComponent(fullKey)}=${multiValue}`; + } + if (value instanceof Set) { + const valueAsArray = Array.from(value); + return querystringSingleKey(key, valueAsArray, keyPrefix); + } + if (value instanceof Date) { + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; + } + if (value instanceof Object) { + return querystring(value as HTTPQuery, fullKey); + } + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`; +} + +export function exists(json: any, key: string) { + const value = json[key]; + return value !== null && value !== undefined; +} + +export function mapValues(data: any, fn: (item: any) => any) { + const result: { [key: string]: any } = {}; + for (const key of Object.keys(data)) { + result[key] = fn(data[key]); + } + return result; +} + +// Pass-through serializer for `any`-typed properties in form data. See #1877. +export function anyToJSON(value: any): any { + return value; +} + +export function canConsumeForm(consumes: Consume[]): boolean { + for (const consume of consumes) { + if (consume.contentType?.startsWith('multipart/form-data') == true) { + return true; + } + } + return false; +} + +export interface Consume { + contentType: string; +} + +export interface RequestContext { + fetch: FetchAPI; + url: string; + init: RequestInit; +} + +export interface ResponseContext { + fetch: FetchAPI; + url: string; + init: RequestInit; + response: Response; +} + +export interface ErrorContext { + fetch: FetchAPI; + url: string; + init: RequestInit; + error: unknown; + response?: Response; +} + +export interface Middleware { + pre?(context: RequestContext): Promise; + post?(context: ResponseContext): Promise; + onError?(context: ErrorContext): Promise; +} + +export interface ApiResponse { + raw: Response; + value(): Promise; +} + +export interface ResponseTransformer { + (json: any): T; +} + +export class JSONApiResponse { + constructor(public raw: Response, private transformer: ResponseTransformer = (jsonValue: any) => jsonValue) {} + + async value(): Promise { + return this.transformer(await this.raw.json()); + } +} + +export class VoidApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return undefined; + } +} + +export class BlobApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return await this.raw.blob(); + }; +} + +export class TextApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return await this.raw.text(); + }; +} diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.esm.json b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.esm.json new file mode 100644 index 000000000000..2c0331cce040 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "esnext", + "outDir": "dist/esm" + } +} diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.json b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.json new file mode 100644 index 000000000000..f1d5adffdbf7 --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "declaration": true, + "target": "es6", + "module": "commonjs", + "outDir": "dist", + "rootDir": "src", + "typeRoots": [ + "node_modules/@types" + ] + }, + "exclude": [ + "dist", + "node_modules" + ] +} From eec586ebb9786910db8939c265c1ac59acf85bf1 Mon Sep 17 00:00:00 2001 From: Antoine Date: Fri, 7 Aug 2026 20:05:57 +0200 Subject: [PATCH 11/11] #6708 : answer the review of the split-by-content-type sample Three of the four points raised were about the sample, which is what the sample is for - the output is readable now. A media type is case-insensitive (RFC 9110), so a server answering `Application/PDF` fell through the dispatch chain and had its body decoded as the default content-type. Both sides of the comparison are lower-cased now. The merged operation only advertised one media type per axis: the split narrows each variant to a single one and the merge never put them back, so the generated documentation hid that createReport also accepts a patch body and can answer with a PDF. The union is restored on the merged operation. apis.mustache reads consumes only where the request axis was not split - a case where the union is the single value anyway - and never reads produces, so nothing but the documentation changes. The sample demonstrated the request axis with an `application/xml` body backed by an object schema. typescript-fetch has no XML serialiser and JSON-encodes that body under an XML Content-Type - with or without this option, as generating the same spec with the option off shows. The behaviour is not this option's doing, but advertising it in the sample promised something the generator does not deliver, so the sample now splits on `application/merge-patch+json`, which it does. The limitation is stated in docs/global-properties.md instead: the option decides which content-types get an operation, not how a body is encoded. The remaining point, body serialisation reading the pre-override header map in runtime.ts, is upstream code this branch does not touch; it applies to every typescript-fetch client and belongs in its own change. --- docs/global-properties.md | 15 +++-- .../TypeScriptFetchClientCodegen.java | 30 ++++++++- .../resources/typescript-fetch/apis.mustache | 9 +-- ...ssue6708-split-by-content-type-sample.yaml | 12 ++-- .../.openapi-generator/FILES | 4 +- .../builds/split-by-content-type/README.md | 2 +- .../split-by-content-type/docs/FilesApi.md | 4 +- .../split-by-content-type/docs/OrderApi.md | 2 +- .../split-by-content-type/docs/ReportApi.md | 6 +- .../docs/{ReportXml.md => ReportPatch.md} | 12 ++-- .../src/apis/FilesApi.ts | 4 +- .../src/apis/OrderApi.ts | 4 +- .../src/apis/ReportApi.ts | 22 +++---- .../split-by-content-type/src/models/Order.ts | 2 +- .../src/models/Receipt.ts | 2 +- .../src/models/Report.ts | 2 +- .../src/models/ReportPatch.ts | 63 +++++++++++++++++++ .../src/models/ReportXml.ts | 63 ------------------- .../split-by-content-type/src/models/index.ts | 2 +- .../split-by-content-type/src/runtime.ts | 2 +- 20 files changed, 150 insertions(+), 112 deletions(-) rename samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/{ReportXml.md => ReportPatch.md} (70%) create mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportPatch.ts delete mode 100644 samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts diff --git a/docs/global-properties.md b/docs/global-properties.md index 359a2df0d9df..9ba39898d33c 100644 --- a/docs/global-properties.md +++ b/docs/global-properties.md @@ -31,7 +31,7 @@ first one is normally kept, which leaves the others unreachable. With `splitOper such an operation is generated once per content-type instead — the cartesian product of the request and response axes, deduplicated by schema — each with a typed, collision-free operation id built from the base one: `With` for the request axis, `As` for the response axis, as in -`createReportWithXmlAsPdf`. +`createReportWithMergePatchAsPdf`. The content-type declared first on each axis is the default one, consistently with the rest of the generator. The option is opt-in and off by default, because it changes the shape of the generated API. @@ -46,7 +46,7 @@ selected by overloads on `accept`. ```ts export type CreateReportRequest = runtime.ExclusiveUnion< | { contentType?: 'application/json'; report?: Report; } - | { contentType: 'application/xml'; reportXml?: ReportXml; } + | { contentType: 'application/merge-patch+json'; reportPatch?: ReportPatch; } >; async createReport(requestParameters: CreateReportRequest & { accept?: 'application/json' }, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; @@ -54,8 +54,8 @@ async createReport(requestParameters: CreateReportRequest & { accept: 'applicati ``` `ExclusiveUnion` makes the members mutually exclusive, by declaring on each of them the keys it does not -have as `never`. Without it nothing stops a caller from handing an XML body to the JSON member and having it -silently sent as JSON: excess property checking, which would normally reject the surplus property, treats a +have as `never`. Without it nothing stops a caller from handing a patch body to the JSON member and having it +sent under the wrong content-type: excess property checking, which would normally reject the surplus property, treats a key present in *any* member of a union as known, so it never fires here — for an object literal no more than for a variable. What rejects most shapes is unrelated: weak type detection when every property of a member is optional, a missing required property otherwise. A member with a required parameter and an optional body @@ -66,6 +66,13 @@ gathered in a single body, so the union member carries them as they are and the that content-type's branch of the switch. `Content-Type` is set in each branch rather than once up front, because a multipart body must not set it at all — `fetch` adds it with the boundary it generates. +The option decides *which* content-types get their own operation; it does not change how a body is +serialised. Each variant is handed to the generator's existing encoders, so a media type the generator has +no encoder for is still sent the way it always was — `typescript-fetch`, for one, has no XML serialiser, and +an `application/xml` body backed by an object schema is JSON-encoded under an XML `Content-Type` exactly as +it is without this option. Splitting makes such a content-type reachable; teaching the generator to encode +it is a separate matter. + One case is left split rather than merged, with a warning: every operation when `useSingleRequestParameter` is off, since the parameters are then spread over the signature and there is no request object to carry the discriminant. The separate, individually typed methods the split produced are then generated as they are, diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java index 8ed649efcb8b..f713a7e677d7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java @@ -42,6 +42,7 @@ import java.io.File; import java.util.*; import java.util.function.BiConsumer; +import java.util.function.Function; import java.util.stream.Collectors; import static java.util.Objects.nonNull; @@ -1084,6 +1085,13 @@ private void mergeContentTypeVariants(OperationsMap operations) { merged.contentTypeResponseDispatch = dispatch; } + // the split narrowed each variant to a single media type per axis; the merged operation speaks + // them all again, so its documentation says so. apis.mustache reads consumes only where the + // request axis was not split - a case where this union is the single value anyway - and never + // reads produces, so this is documentation only. + base.consumes = mediaTypesOf(requestVariants, v -> v.consumes); + base.produces = mediaTypesOf(responseVariants, v -> v.produces); + variants.stream().filter(op -> op != base).forEach(superseded::add); } @@ -1091,6 +1099,25 @@ private void mergeContentTypeVariants(OperationsMap operations) { allOperations.removeAll(superseded); } + /** + * The media types the variants of one axis declare, in the axis order, without repeating one two + * variants happen to share. + */ + private static List> mediaTypesOf(List axis, + Function>> field) { + Map> byMediaType = new LinkedHashMap<>(); + for (ContentTypeVariant variant : axis) { + List> declared = field.apply(variant); + if (declared == null) { + continue; + } + for (Map entry : declared) { + byMediaType.putIfAbsent(entry.get("mediaType"), entry); + } + } + return byMediaType.isEmpty() ? null : new ArrayList<>(byMediaType.values()); + } + /** * One entry per distinct request content-type, in declaration order, carrying the body that content-type * expects as the generator resolved it. A single-element list means the request axis was not split. @@ -1124,6 +1151,7 @@ private List responseVariantsOf(List varia entry.isArray = variant.isArray; entry.isMap = variant.isMap; entry.uniqueItems = variant.uniqueItems; + entry.produces = variant.produces; }); } @@ -1163,7 +1191,7 @@ public static class ContentTypeVariant { public List allParams, formParams; public CodegenParameter bodyParam; public boolean hasFormParams; - public List> consumes; + public List> consumes, produces; // response axis public boolean isResponseFile, returnTypeIsPrimitive, returnSimpleType, isArray, isMap, uniqueItems; diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache index 31890e42aa20..9958fe4a7b06 100644 --- a/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache @@ -399,15 +399,16 @@ export class {{classname}} extends runtime.BaseAPI { {{! dispatch on the content-type the server actually returned, not on the requested `accept`: the header is a request, and a server is free not to honour it }} {{! type/subtype only, compared exactly: startsWith would let application/json win over - application/json-patch+json, and a `; charset=` parameter would defeat an equality test }} - const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + application/json-patch+json, and a `; charset=` parameter would defeat an equality test. + Lower-cased on both sides because a media type is case-insensitive (RFC 9110). }} + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim().toLowerCase(); {{#contentTypeResponseDispatch}} {{#-first}} - if (responseContentType === '{{mediaType}}') { + if (responseContentType === '{{#lambda.lowercase}}{{mediaType}}{{/lambda.lowercase}}') { {{/-first}} {{^-first}} {{^-last}} - } else if (responseContentType === '{{mediaType}}') { + } else if (responseContentType === '{{#lambda.lowercase}}{{mediaType}}{{/lambda.lowercase}}') { {{/-last}} {{/-first}} {{#-last}} diff --git a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml index 01a42d7f8c2d..a4e2d0b0a043 100644 --- a/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/issue6708-split-by-content-type-sample.yaml @@ -4,7 +4,9 @@ info: description: > Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request - split that mixes JSON and multipart, and an enum parameter carried by a split operation. + split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every + media type here is one the generator can actually serialise: the option divides operations by + content-type, it does not give the generator encoders it never had. version: 1.0.0 paths: # Response axis only: the request body is untouched, `accept` selects the return type. @@ -39,9 +41,9 @@ paths: application/json: schema: $ref: '#/components/schemas/Report' - application/xml: + application/merge-patch+json: schema: - $ref: '#/components/schemas/ReportXml' + $ref: '#/components/schemas/ReportPatch' responses: '200': description: ok @@ -138,10 +140,10 @@ components: type: string name: type: string - ReportXml: + ReportPatch: type: object properties: - ref: + name: type: string Receipt: type: object diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES index f78f9a9f7f4a..83aa803f3d37 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/.openapi-generator/FILES @@ -7,7 +7,7 @@ docs/OrderApi.md docs/Receipt.md docs/Report.md docs/ReportApi.md -docs/ReportXml.md +docs/ReportPatch.md package.json src/apis/FilesApi.ts src/apis/OrderApi.ts @@ -17,7 +17,7 @@ src/index.ts src/models/Order.ts src/models/Receipt.ts src/models/Report.ts -src/models/ReportXml.ts +src/models/ReportPatch.ts src/models/index.ts src/runtime.ts tsconfig.esm.json diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md index c9a3225a49ea..1925622f22c8 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/README.md @@ -62,7 +62,7 @@ All URIs are relative to *http://localhost* - [Order](docs/Order.md) - [Receipt](docs/Receipt.md) - [Report](docs/Report.md) -- [ReportXml](docs/ReportXml.md) +- [ReportPatch](docs/ReportPatch.md) ### Authorization diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md index 06984876acd4..b1675500b1ed 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/FilesApi.md @@ -62,7 +62,7 @@ No authorization required ### HTTP request headers -- **Content-Type**: `application/json` +- **Content-Type**: `application/json`, `multipart/form-data` - **Accept**: `application/json` @@ -131,7 +131,7 @@ No authorization required ### HTTP request headers - **Content-Type**: `multipart/form-data` -- **Accept**: `application/json` +- **Accept**: `application/json`, `application/pdf` ### HTTP response details diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md index 813f0f289689..fbd39f55998a 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/OrderApi.md @@ -62,7 +62,7 @@ No authorization required ### HTTP request headers - **Content-Type**: Not defined -- **Accept**: `application/json` +- **Accept**: `application/json`, `application/pdf` ### HTTP response details diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md index 13ad8bb1ce77..81679a4e4ebc 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportApi.md @@ -62,8 +62,8 @@ No authorization required ### HTTP request headers -- **Content-Type**: `application/json` -- **Accept**: `application/json` +- **Content-Type**: `application/json`, `application/merge-patch+json` +- **Accept**: `application/json`, `application/pdf` ### HTTP response details @@ -128,7 +128,7 @@ No authorization required ### HTTP request headers - **Content-Type**: Not defined -- **Accept**: `application/json` +- **Accept**: `application/json`, `application/directlog` ### HTTP response details diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportPatch.md similarity index 70% rename from samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md rename to samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportPatch.md index 2d1b34fa4d5f..53ef5b401a74 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportXml.md +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/docs/ReportPatch.md @@ -1,22 +1,22 @@ -# ReportXml +# ReportPatch ## Properties Name | Type ------------ | ------------- -`ref` | string +`name` | string ## Example ```typescript -import type { ReportXml } from '@openapitools/typescript-fetch-split-by-content-type' +import type { ReportPatch } from '@openapitools/typescript-fetch-split-by-content-type' // TODO: Update the object below with actual values const example = { - "ref": null, -} satisfies ReportXml + "name": null, +} satisfies ReportPatch console.log(example) @@ -25,7 +25,7 @@ const exampleJSON: string = JSON.stringify(example) console.log(exampleJSON) // Parse the JSON string back to an object -const exampleParsed = JSON.parse(exampleJSON) as ReportXml +const exampleParsed = JSON.parse(exampleJSON) as ReportPatch console.log(exampleParsed) ``` diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts index 1cc17b729765..0c786c5dcd5c 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/FilesApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 * @@ -156,7 +156,7 @@ export class FilesApi extends runtime.BaseAPI { const requestOptions = await this.uploadRequestOpts(requestParameters); const response = await this.request(requestOptions, initOverrides); - const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim().toLowerCase(); if (responseContentType === 'application/pdf') { return new runtime.BlobApiResponse(response) as any; } else { diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts index 885906a5195f..aed1acf1f6b1 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/OrderApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 * @@ -61,7 +61,7 @@ export class OrderApi extends runtime.BaseAPI { const requestOptions = await this.getOrdersRequestOpts(requestParameters); const response = await this.request(requestOptions, initOverrides); - const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim().toLowerCase(); if (responseContentType === 'application/pdf') { return new runtime.BlobApiResponse(response) as any; } else { diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts index fecd290d0d24..0cb4e28ae8b4 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/apis/ReportApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 * @@ -24,14 +24,14 @@ import { ReportToJSON, } from '../models/Report'; import { - type ReportXml, - ReportXmlFromJSON, - ReportXmlToJSON, -} from '../models/ReportXml'; + type ReportPatch, + ReportPatchFromJSON, + ReportPatchToJSON, +} from '../models/ReportPatch'; export type CreateReportRequest = runtime.ExclusiveUnion< | { contentType?: 'application/json'; report?: Report; } - | { contentType: 'application/xml'; reportXml?: ReportXml; } + | { contentType: 'application/merge-patch+json'; reportPatch?: ReportPatch; } >; export type GetReportRequest = @@ -58,9 +58,9 @@ export class ReportApi extends runtime.BaseAPI { let body: any; switch (requestParameters.contentType) { - case 'application/xml': { - headerParameters['Content-Type'] = 'application/xml'; - body = ReportXmlToJSON(requestParameters['reportXml']); + case 'application/merge-patch+json': { + headerParameters['Content-Type'] = 'application/merge-patch+json'; + body = ReportPatchToJSON(requestParameters['reportPatch']); break; } default: { @@ -86,7 +86,7 @@ export class ReportApi extends runtime.BaseAPI { const requestOptions = await this.createReportRequestOpts(requestParameters); const response = await this.request(requestOptions, initOverrides); - const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim().toLowerCase(); if (responseContentType === 'application/pdf') { return new runtime.BlobApiResponse(response) as any; } else { @@ -140,7 +140,7 @@ export class ReportApi extends runtime.BaseAPI { const requestOptions = await this.getReportRequestOpts(requestParameters); const response = await this.request(requestOptions, initOverrides); - const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim(); + const responseContentType = (response.headers.get('content-type') ?? '').split(';')[0].trim().toLowerCase(); if (responseContentType === 'application/directlog') { return new runtime.BlobApiResponse(response) as any; } else { diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts index 804d08ea297f..1ae006797d9e 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Order.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 * diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts index 0180387291e3..97f9bbb5003e 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Receipt.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 * diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts index e03f85f768d7..1bf0d9c1d2a1 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/Report.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 * diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportPatch.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportPatch.ts new file mode 100644 index 000000000000..d89ed019828b --- /dev/null +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportPatch.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * split operations by content-type (issue 6708) + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. + * + * 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 { mapValues } from '../runtime'; +/** + * + * @export + * @interface ReportPatch + */ +export interface ReportPatch { + /** + * + */ + name?: string; +} + +/** + * Check if a given object implements the ReportPatch interface. + */ +export function instanceOfReportPatch(value: object): value is ReportPatch { + return true; +} + +export function ReportPatchFromJSON(json: any): ReportPatch { + return ReportPatchFromJSONTyped(json, false); +} + +export function ReportPatchFromJSONTyped(json: any, ignoreDiscriminator: boolean): ReportPatch { + if (json == null) { + return json; + } + return { + + 'name': json['name'] == null ? undefined : json['name'], + }; +} + +export function ReportPatchToJSON(json: any): ReportPatch { + return ReportPatchToJSONTyped(json, false); +} + +export function ReportPatchToJSONTyped(value?: ReportPatch | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'name': value['name'], + }; +} + diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts deleted file mode 100644 index c4292c5f4002..000000000000 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/ReportXml.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. - * - * 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 { mapValues } from '../runtime'; -/** - * - * @export - * @interface ReportXml - */ -export interface ReportXml { - /** - * - */ - ref?: string; -} - -/** - * Check if a given object implements the ReportXml interface. - */ -export function instanceOfReportXml(value: object): value is ReportXml { - return true; -} - -export function ReportXmlFromJSON(json: any): ReportXml { - return ReportXmlFromJSONTyped(json, false); -} - -export function ReportXmlFromJSONTyped(json: any, ignoreDiscriminator: boolean): ReportXml { - if (json == null) { - return json; - } - return { - - 'ref': json['ref'] == null ? undefined : json['ref'], - }; -} - -export function ReportXmlToJSON(json: any): ReportXml { - return ReportXmlToJSONTyped(json, false); -} - -export function ReportXmlToJSONTyped(value?: ReportXml | null, ignoreDiscriminator: boolean = false): any { - if (value == null) { - return value; - } - - return { - - 'ref': value['ref'], - }; -} - diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts index f0a53f5591aa..c89a7699d415 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/models/index.ts @@ -3,4 +3,4 @@ export * from './Order'; export * from './Receipt'; export * from './Report'; -export * from './ReportXml'; +export * from './ReportPatch'; diff --git a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts index af99999f0167..f37232b5ec76 100644 --- a/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts +++ b/samples/client/petstore/typescript-fetch/builds/split-by-content-type/src/runtime.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * split operations by content-type (issue 6708) - * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. + * Spec behind the typescript-fetch `split-by-content-type` sample. It gathers the shapes the option has to handle: a response-only split, a split on both axes, a multipart body, a request split that mixes JSON and multipart, and an enum parameter carried by a split operation. Every media type here is one the generator can actually serialise: the option divides operations by content-type, it does not give the generator encoders it never had. * * The version of the OpenAPI document: 1.0.0 *