From dbc42d3d7d1b814de2c3f8c7e4fccb8cc78ae838 Mon Sep 17 00:00:00 2001 From: Raymond Carino Date: Thu, 9 Oct 2025 09:34:16 -0700 Subject: [PATCH 1/5] fix: Apply REMOVE_X_INTERNAL normalizer to nested inline properties When REMOVE_X_INTERNAL=true is set, the normalizer removes the x-internal extension from top-level schemas in components/schemas but fails to remove it from inline object properties within those schemas. This causes issues when: 1. A schema is imported cross-file (e.g., admin.yaml imports from chat.yaml) 2. That schema has an inline object property with x-internal: true 3. The inline property has type: object with nested properties Result: TypeScript generator creates a type reference but no interface definition, causing compilation errors. This fix applies the same x-internal removal logic to normalizeProperties() that already exists in normalizeComponentsSchemas(), ensuring inline properties are handled consistently. Fixes behavior for inline schemas with x-internal in cross-file imports. --- .../java/org/openapitools/codegen/OpenAPINormalizer.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index a53d9655a74a..3d43af5b9c05 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -855,6 +855,13 @@ protected void normalizeProperties(Map properties, Set v } for (Map.Entry propertiesEntry : properties.entrySet()) { Schema property = propertiesEntry.getValue(); + + // remove x-internal if needed (same logic as normalizeComponentsSchemas) + if (property.getExtensions() != null && getRule(REMOVE_X_INTERNAL)) { + if (Boolean.parseBoolean(String.valueOf(property.getExtensions().get(X_INTERNAL)))) { + property.getExtensions().remove(X_INTERNAL); + } + } Schema newProperty = normalizeSchema(property, new HashSet<>()); propertiesEntry.setValue(newProperty); } From 66f5e1c51f2b53c1897ef3abcdf8116f6a222bb9 Mon Sep 17 00:00:00 2001 From: Raymond Carino Date: Thu, 9 Oct 2025 09:45:34 -0700 Subject: [PATCH 2/5] Update modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../java/org/openapitools/codegen/OpenAPINormalizer.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index 3d43af5b9c05..c443c8a302b1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -858,7 +858,14 @@ protected void normalizeProperties(Map properties, Set v // remove x-internal if needed (same logic as normalizeComponentsSchemas) if (property.getExtensions() != null && getRule(REMOVE_X_INTERNAL)) { - if (Boolean.parseBoolean(String.valueOf(property.getExtensions().get(X_INTERNAL)))) { + Object xInternalValue = property.getExtensions().get(X_INTERNAL); + boolean isInternal = false; + if (xInternalValue instanceof Boolean) { + isInternal = (Boolean) xInternalValue; + } else if (xInternalValue instanceof String) { + isInternal = Boolean.parseBoolean((String) xInternalValue); + } + if (isInternal) { property.getExtensions().remove(X_INTERNAL); } } From 435b9426046f737752060a211c46a6e993374d2a Mon Sep 17 00:00:00 2001 From: Raymond Carino Date: Thu, 9 Oct 2025 10:15:46 -0700 Subject: [PATCH 3/5] test: Add test case for REMOVE_X_INTERNAL with inline properties Adds test to verify that REMOVE_X_INTERNAL normalizer correctly removes x-internal extension from inline object properties, not just top-level schemas. --- .../codegen/OpenAPINormalizerTest.java | 36 +++++++++++++++++++ .../resources/3_0/inline_x_internal_test.yaml | 24 +++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 modules/openapi-generator/src/test/resources/3_0/inline_x_internal_test.yaml diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java index 3ea7f1ce8727..833f991c9f60 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java @@ -1153,6 +1153,42 @@ public void testNormalizerClass() { assertEquals(requiredProperties.getRequired(), null); } + + @Test + public void testRemoveXInternalFromInlineProperties() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/inline_x_internal_test.yaml"); + Schema parentSchema = openAPI.getComponents().getSchemas().get("ParentSchema"); + Schema inlineProperty = (Schema) parentSchema.getProperties().get("inlineXInternalProperty"); + + // Before normalization: x-internal should be present on inline property + assertNotNull(inlineProperty.getExtensions()); + assertEquals(inlineProperty.getExtensions().get("x-internal"), true); + + // Run normalizer with REMOVE_X_INTERNAL=true + Map options = new HashMap<>(); + options.put("REMOVE_X_INTERNAL", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + // After normalization: x-internal should be removed from inline property + Schema parentSchemaAfter = openAPI.getComponents().getSchemas().get("ParentSchema"); + Schema inlinePropertyAfter = (Schema) parentSchemaAfter.getProperties().get("inlineXInternalProperty"); + + // x-internal extension should be removed (null or not present in map) + if (inlinePropertyAfter.getExtensions() != null) { + assertNull(inlinePropertyAfter.getExtensions().get("x-internal")); + } + + // The property itself should still exist (we're removing the flag, not the property) + assertNotNull(inlinePropertyAfter); + assertEquals(inlinePropertyAfter.getType(), "object"); + + // Nested properties should still exist + assertNotNull(inlinePropertyAfter.getProperties()); + assertNotNull(inlinePropertyAfter.getProperties().get("nestedField")); + assertNotNull(inlinePropertyAfter.getProperties().get("nestedNumber")); + } + public static class RemoveRequiredNormalizer extends OpenAPINormalizer { public RemoveRequiredNormalizer(OpenAPI openAPI, Map inputRules) { diff --git a/modules/openapi-generator/src/test/resources/3_0/inline_x_internal_test.yaml b/modules/openapi-generator/src/test/resources/3_0/inline_x_internal_test.yaml new file mode 100644 index 000000000000..d5a07461f1d5 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/inline_x_internal_test.yaml @@ -0,0 +1,24 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: Test inline x-internal +components: + schemas: + ParentSchema: + description: Schema with inline x-internal property + type: object + properties: + normalProperty: + type: string + description: A normal property without x-internal + inlineXInternalProperty: + x-internal: true + description: Inline object property marked as x-internal + type: object + properties: + nestedField: + type: string + description: A field inside the inline x-internal object + nestedNumber: + type: integer + description: Another field inside the inline object From c899e9ec96640660c0c7f184e1f1f6991b6853ab Mon Sep 17 00:00:00 2001 From: Raymond Carino Date: Thu, 9 Oct 2025 12:56:16 -0700 Subject: [PATCH 4/5] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../java/org/openapitools/codegen/OpenAPINormalizer.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index c443c8a302b1..1e8863385de4 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -864,10 +864,9 @@ protected void normalizeProperties(Map properties, Set v isInternal = (Boolean) xInternalValue; } else if (xInternalValue instanceof String) { isInternal = Boolean.parseBoolean((String) xInternalValue); - } - if (isInternal) { - property.getExtensions().remove(X_INTERNAL); - } + if (property.getExtensions() != null && getRule(REMOVE_X_INTERNAL) + && Boolean.parseBoolean(String.valueOf(property.getExtensions().get(X_INTERNAL)))) { + property.getExtensions().remove(X_INTERNAL); } Schema newProperty = normalizeSchema(property, new HashSet<>()); propertiesEntry.setValue(newProperty); From 60cf734459b535da60ea5dab605f8e83f052763c Mon Sep 17 00:00:00 2001 From: Raymond Carino Date: Fri, 10 Oct 2025 17:24:14 -0700 Subject: [PATCH 5/5] Revert "Apply suggestion from @Copilot" This reverts commit c899e9ec96640660c0c7f184e1f1f6991b6853ab. --- .../java/org/openapitools/codegen/OpenAPINormalizer.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index 1e8863385de4..c443c8a302b1 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -864,9 +864,10 @@ protected void normalizeProperties(Map properties, Set v isInternal = (Boolean) xInternalValue; } else if (xInternalValue instanceof String) { isInternal = Boolean.parseBoolean((String) xInternalValue); - if (property.getExtensions() != null && getRule(REMOVE_X_INTERNAL) - && Boolean.parseBoolean(String.valueOf(property.getExtensions().get(X_INTERNAL)))) { - property.getExtensions().remove(X_INTERNAL); + } + if (isInternal) { + property.getExtensions().remove(X_INTERNAL); + } } Schema newProperty = normalizeSchema(property, new HashSet<>()); propertiesEntry.setValue(newProperty);