feature: [typescript-fetch] add model suffix support - #24873
feature: [typescript-fetch] add model suffix support#24873WojciechZankowski wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
5 issues found across 47 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java">
<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java:567">
P3: The new suffix test only asserts the suffixed model files and their `export interface`/`export type` declarations, but never checks that references to these models were renamed consistently elsewhere. If the suffix renaming updated only the model filenames/declarations and not the imports in `apis/*.ts`, the `models/index.ts` barrel, or cross-model `import type { TestBResource } from './TestBResource'` statements, the output would not compile and this test would still pass. The sibling tests in this file (e.g. `testGeneratedFilenamesInKebabCaseWithAdditionalModelPrefix`) assert exactly that, e.g. `} from '../models/some-prefix-pet';`. Add an assertion on an API-side or a referencing model import (e.g. that `TestResponseResource.ts` imports `TestBResource` from `./TestBResource`) so the suffix feature is verified end-to-end.</violation>
</file>
<file name="samples/client/petstore/typescript-fetch/builds/model-suffix/README.md">
<violation number="1" location="samples/client/petstore/typescript-fetch/builds/model-suffix/README.md:21">
P2: The README example imports `import type { TestRequest } from '@openapitools/typescript-fetch-model-suffix';`, but no `TestRequest` symbol is exported from this package. The build was generated with `modelSuffix: Resource`, so every model (and any generated request/parameter interface) carries the `Resource` suffix. `src/models/index.ts` exports only `*Resource` types, and a repository-wide search finds no `TestRequest`. Following the README would therefore fail to compile. The root cause is `api_example.mustache`, which renders `import type { {{operationIdCamelCase}}Request }` without applying the model suffix (and does not gate on request-interface generation, which is disabled for this config).</violation>
</file>
<file name="samples/client/petstore/typescript-fetch/builds/model-suffix/src/runtime.ts">
<violation number="1" location="samples/client/petstore/typescript-fetch/builds/model-suffix/src/runtime.ts:179">
P2: When an `initOverrides` callback changes `headers`, this check still uses the original request headers, so JSON bodies are serialized according to stale content-type metadata. Inspect the effective `overriddenInit.headers` (including `Headers` and case-insensitive names) before deciding whether to `JSON.stringify` the body.</violation>
</file>
<file name="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java">
<violation number="1" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java:61">
P3: `CLASS_NAME_SUFFIX_PATTERN` is an immutable constant but is neither `static final` nor `final`, unlike the other compile-time constants in this class. Mark it `private static final String`.</violation>
<violation number="2" location="modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java:358">
P2: The new `modelSuffix` option is functionally identical to the existing global `modelNameSuffix` option (CodegenConstants.MODEL_NAME_SUFFIX), which typescript-fetch already supports end to end: DefaultCodegen.processOpts reads `modelNameSuffix` into the same `modelNameSuffix` field (DefaultCodegen.java:437), and AbstractTypeScriptClientCodegen.toModelName appends it via addSuffix (AbstractTypeScriptClientCodegen.java:623). Both paths produce the same output, so `modelSuffix` adds a second, inconsistently-named (`modelSuffix` vs `modelNameSuffix`) way to do the same thing and silently overrides `modelNameSuffix` when both are provided. Consider reusing the existing `modelNameSuffix` option and only adding the missing validation there, rather than introducing a duplicate option.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
| Configuration, | ||
| DefaultApi, | ||
| } from '@openapitools/typescript-fetch-model-suffix'; | ||
| import type { TestRequest } from '@openapitools/typescript-fetch-model-suffix'; |
There was a problem hiding this comment.
P2: The README example imports import type { TestRequest } from '@openapitools/typescript-fetch-model-suffix';, but no TestRequest symbol is exported from this package. The build was generated with modelSuffix: Resource, so every model (and any generated request/parameter interface) carries the Resource suffix. src/models/index.ts exports only *Resource types, and a repository-wide search finds no TestRequest. Following the README would therefore fail to compile. The root cause is api_example.mustache, which renders import type { {{operationIdCamelCase}}Request } without applying the model suffix (and does not gate on request-interface generation, which is disabled for this config).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/typescript-fetch/builds/model-suffix/README.md, line 21:
<comment>The README example imports `import type { TestRequest } from '@openapitools/typescript-fetch-model-suffix';`, but no `TestRequest` symbol is exported from this package. The build was generated with `modelSuffix: Resource`, so every model (and any generated request/parameter interface) carries the `Resource` suffix. `src/models/index.ts` exports only `*Resource` types, and a repository-wide search finds no `TestRequest`. Following the README would therefore fail to compile. The root cause is `api_example.mustache`, which renders `import type { {{operationIdCamelCase}}Request }` without applying the model suffix (and does not gate on request-interface generation, which is disabled for this config).</comment>
<file context>
@@ -0,0 +1,124 @@
+ Configuration,
+ DefaultApi,
+} from '@openapitools/typescript-fetch-model-suffix';
+import type { TestRequest } from '@openapitools/typescript-fetch-model-suffix';
+
+async function example() {
</file context>
| || (overriddenInit.body instanceof URLSearchParams) | ||
| || isBlob(overriddenInit.body)) { | ||
| body = overriddenInit.body; | ||
| } else if (this.isJsonMime(headers['Content-Type'])) { |
There was a problem hiding this comment.
P2: When an initOverrides callback changes headers, this check still uses the original request headers, so JSON bodies are serialized according to stale content-type metadata. Inspect the effective overriddenInit.headers (including Headers and case-insensitive names) before deciding whether to JSON.stringify the body.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/typescript-fetch/builds/model-suffix/src/runtime.ts, line 179:
<comment>When an `initOverrides` callback changes `headers`, this check still uses the original request headers, so JSON bodies are serialized according to stale content-type metadata. Inspect the effective `overriddenInit.headers` (including `Headers` and case-insensitive names) before deciding whether to `JSON.stringify` the body.</comment>
<file context>
@@ -0,0 +1,505 @@
+ || (overriddenInit.body instanceof URLSearchParams)
+ || isBlob(overriddenInit.body)) {
+ body = overriddenInit.body;
+ } else if (this.isJsonMime(headers['Content-Type'])) {
+ body = JSON.stringify(overriddenInit.body);
+ } else {
</file context>
| } | ||
|
|
||
| if (additionalProperties.containsKey(MODEL_SUFFIX)) { | ||
| this.modelNameSuffix = additionalProperties.get(MODEL_SUFFIX).toString(); |
There was a problem hiding this comment.
P2: The new modelSuffix option is functionally identical to the existing global modelNameSuffix option (CodegenConstants.MODEL_NAME_SUFFIX), which typescript-fetch already supports end to end: DefaultCodegen.processOpts reads modelNameSuffix into the same modelNameSuffix field (DefaultCodegen.java:437), and AbstractTypeScriptClientCodegen.toModelName appends it via addSuffix (AbstractTypeScriptClientCodegen.java:623). Both paths produce the same output, so modelSuffix adds a second, inconsistently-named (modelSuffix vs modelNameSuffix) way to do the same thing and silently overrides modelNameSuffix when both are provided. Consider reusing the existing modelNameSuffix option and only adding the missing validation there, rather than introducing a duplicate option.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java, line 358:
<comment>The new `modelSuffix` option is functionally identical to the existing global `modelNameSuffix` option (CodegenConstants.MODEL_NAME_SUFFIX), which typescript-fetch already supports end to end: DefaultCodegen.processOpts reads `modelNameSuffix` into the same `modelNameSuffix` field (DefaultCodegen.java:437), and AbstractTypeScriptClientCodegen.toModelName appends it via addSuffix (AbstractTypeScriptClientCodegen.java:623). Both paths produce the same output, so `modelSuffix` adds a second, inconsistently-named (`modelSuffix` vs `modelNameSuffix`) way to do the same thing and silently overrides `modelNameSuffix` when both are provided. Consider reusing the existing `modelNameSuffix` option and only adding the missing validation there, rather than introducing a duplicate option.</comment>
<file context>
@@ -335,6 +354,11 @@ public void processOpts() {
}
+ if (additionalProperties.containsKey(MODEL_SUFFIX)) {
+ this.modelNameSuffix = additionalProperties.get(MODEL_SUFFIX).toString();
+ validateClassSuffixArgument("Model", modelNameSuffix);
+ }
</file context>
|
|
||
| File output = generate(properties, "src/test/resources/3_0/typescript-fetch/oneOf.yaml"); | ||
|
|
||
| Path modelWithSuffix = Paths.get(output + "/models/TestBResource.ts"); |
There was a problem hiding this comment.
P3: The new suffix test only asserts the suffixed model files and their export interface/export type declarations, but never checks that references to these models were renamed consistently elsewhere. If the suffix renaming updated only the model filenames/declarations and not the imports in apis/*.ts, the models/index.ts barrel, or cross-model import type { TestBResource } from './TestBResource' statements, the output would not compile and this test would still pass. The sibling tests in this file (e.g. testGeneratedFilenamesInKebabCaseWithAdditionalModelPrefix) assert exactly that, e.g. } from '../models/some-prefix-pet';. Add an assertion on an API-side or a referencing model import (e.g. that TestResponseResource.ts imports TestBResource from ./TestBResource) so the suffix feature is verified end-to-end.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java, line 567:
<comment>The new suffix test only asserts the suffixed model files and their `export interface`/`export type` declarations, but never checks that references to these models were renamed consistently elsewhere. If the suffix renaming updated only the model filenames/declarations and not the imports in `apis/*.ts`, the `models/index.ts` barrel, or cross-model `import type { TestBResource } from './TestBResource'` statements, the output would not compile and this test would still pass. The sibling tests in this file (e.g. `testGeneratedFilenamesInKebabCaseWithAdditionalModelPrefix`) assert exactly that, e.g. `} from '../models/some-prefix-pet';`. Add an assertion on an API-side or a referencing model import (e.g. that `TestResponseResource.ts` imports `TestBResource` from `./TestBResource`) so the suffix feature is verified end-to-end.</comment>
<file context>
@@ -561,6 +557,22 @@ public void containsESMTSConfigFileInCaseOfES6AndNPM() {
+
+ File output = generate(properties, "src/test/resources/3_0/typescript-fetch/oneOf.yaml");
+
+ Path modelWithSuffix = Paths.get(output + "/models/TestBResource.ts");
+ TestUtils.assertFileExists(modelWithSuffix);
+ TestUtils.assertFileContains(modelWithSuffix, "export interface TestBResource");
</file context>
| public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodegen { | ||
| private final Logger LOGGER = LoggerFactory.getLogger(TypeScriptFetchClientCodegen.class); | ||
|
|
||
| private static String CLASS_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9]*$"; |
There was a problem hiding this comment.
P3: CLASS_NAME_SUFFIX_PATTERN is an immutable constant but is neither static final nor final, unlike the other compile-time constants in this class. Mark it private static final String.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java, line 61:
<comment>`CLASS_NAME_SUFFIX_PATTERN` is an immutable constant but is neither `static final` nor `final`, unlike the other compile-time constants in this class. Mark it `private static final String`.</comment>
<file context>
@@ -58,6 +58,8 @@
public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodegen {
private final Logger LOGGER = LoggerFactory.getLogger(TypeScriptFetchClientCodegen.class);
+ private static String CLASS_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9]*$";
+
public static final String NPM_REPOSITORY = "npmRepository";
</file context>
PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
Summary by cubic
Adds a
modelSuffixconfig option to thetypescript-fetchgenerator so generated model names and filenames can be appended with a custom suffix.samples/client/petstore/typescript-fetch/builds/model-suffix.Written for commit 0785758. Summary will update on new commits.