Skip to content

Introduce option 'importFileExtension' to typescript-axios (#21343) #21344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generators/typescript-axios.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |PascalCase|
|enumPropertyNamingReplaceSpecialChar|Set to true to replace '-' and '+' symbols with 'minus_' and 'plus_' in enum of type string| |false|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|importFileExtension|File extension to use with relative imports. Set it to '.js' or '.mjs' when using [ESM](https://nodejs.org/api/esm.html).| ||
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|licenseName|The name of the license| |Unlicense|
|modelPackage|package for generated models| |null|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ public class TypeScriptAxiosClientCodegen extends AbstractTypeScriptClientCodege
public static final String WITH_NODE_IMPORTS = "withNodeImports";
public static final String STRING_ENUMS = "stringEnums";
public static final String STRING_ENUMS_DESC = "Generate string enums instead of objects for enum values.";
public static final String IMPORT_FILE_EXTENSION_SWITCH = "importFileExtension";
public static final String IMPORT_FILE_EXTENSION_SWITCH_DESC = "File extension to use with relative imports. Set it to '.js' or '.mjs' when using [ESM](https://nodejs.org/api/esm.html).";
public static final String USE_SQUARE_BRACKETS_IN_ARRAY_NAMES = "useSquareBracketsInArrayNames";
public static final String AXIOS_VERSION = "axiosVersion";
public static final String DEFAULT_AXIOS_VERSION = "^1.6.1";

@Getter @Setter
protected String npmRepository = null;
protected Boolean stringEnums = false;
protected String importFileExtension = "";

@Getter @Setter
protected String axiosVersion = DEFAULT_AXIOS_VERSION;
Expand Down Expand Up @@ -88,6 +91,7 @@ public TypeScriptAxiosClientCodegen() {
this.cliOptions.add(new CliOption(USE_SINGLE_REQUEST_PARAMETER, "Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(WITH_NODE_IMPORTS, "Setting this property to true adds imports for NodeJS", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(STRING_ENUMS, STRING_ENUMS_DESC).defaultValue(String.valueOf(this.stringEnums)));
this.cliOptions.add(new CliOption(IMPORT_FILE_EXTENSION_SWITCH, IMPORT_FILE_EXTENSION_SWITCH_DESC, SchemaTypeUtil.STRING_TYPE).defaultValue(this.importFileExtension));
this.cliOptions.add(new CliOption(USE_SQUARE_BRACKETS_IN_ARRAY_NAMES, "Setting this property to true will add brackets to array attribute names, e.g. my_values[].", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
this.cliOptions.add(new CliOption(AXIOS_VERSION, "Use this property to override the axios version in package.json").defaultValue(DEFAULT_AXIOS_VERSION));
// Templates have no mapping between formatted property names and original base names so use only "original" and remove this option
Expand Down Expand Up @@ -162,6 +166,14 @@ public void processOpts() {
additionalProperties.put("stringEnums", this.stringEnums);
}

if (additionalProperties.containsKey(IMPORT_FILE_EXTENSION_SWITCH)) {
this.importFileExtension = additionalProperties.get(IMPORT_FILE_EXTENSION_SWITCH).toString();
if (!this.importFileExtension.isEmpty() && !this.importFileExtension.startsWith(".")) {
this.importFileExtension = "." + this.importFileExtension;
}
additionalProperties.put("importFileExtension", this.importFileExtension);
}

if (additionalProperties.containsKey(NPM_NAME)) {
addNpmPackageGeneration();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{{>licenseInfo}}

{{^withSeparateModelsAndApi}}
import type { Configuration } from './configuration';
import type { Configuration } from './configuration{{importFileExtension}}';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
{{#withNodeImports}}
Expand All @@ -17,9 +17,9 @@ import FormData from 'form-data'
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common';
import type { RequestArgs } from './base';
import type { RequestArgs } from './base{{importFileExtension}}';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from './base';
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerMap } from './base{{importFileExtension}}';

{{#models}}
{{#model}}{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{#oneOf}}{{#-first}}{{>modelOneOf}}{{/-first}}{{/oneOf}}{{^isEnum}}{{^oneOf}}{{>modelGeneric}}{{/oneOf}}{{/isEnum}}{{/model}}
Expand All @@ -28,6 +28,6 @@ import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError, operationServerM
{{>apiInner}}
{{/apis}}{{/apiInfo}}
{{/withSeparateModelsAndApi}}{{#withSeparateModelsAndApi}}
{{#apiInfo}}{{#apis}}{{#operations}}export * from './{{tsApiPackage}}/{{classFilename}}';
{{#apiInfo}}{{#apis}}{{#operations}}export * from './{{tsApiPackage}}/{{classFilename}}{{importFileExtension}}';
{{/operations}}{{/apis}}{{/apiInfo}}
{{/withSeparateModelsAndApi}}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* eslint-disable */
{{>licenseInfo}}

import type { Configuration } from '{{apiRelativeToRoot}}configuration';
import type { Configuration } from '{{apiRelativeToRoot}}configuration{{importFileExtension}}';
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
import globalAxios from 'axios';
{{#withNodeImports}}
Expand All @@ -16,12 +16,12 @@ import FormData from 'form-data'
{{/withNodeImports}}
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '{{apiRelativeToRoot}}common';
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '{{apiRelativeToRoot}}common{{importFileExtension}}';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, type RequestArgs, BaseAPI, RequiredError, operationServerMap } from '{{apiRelativeToRoot}}base';
import { BASE_PATH, COLLECTION_FORMATS, type RequestArgs, BaseAPI, RequiredError, operationServerMap } from '{{apiRelativeToRoot}}base{{importFileExtension}}';
{{#imports}}
// @ts-ignore
import type { {{classname}} } from '{{apiRelativeToRoot}}{{tsModelPackage}}';
import type { {{classname}} } from '{{apiRelativeToRoot}}{{tsModelPackage}}{{importFileExtension}}';
{{/imports}}
{{/withSeparateModelsAndApi}}
{{^withSeparateModelsAndApi}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* eslint-disable */
{{>licenseInfo}}

import type { Configuration } from './configuration';
import type { Configuration } from './configuration{{importFileExtension}}';
// Some imports not used depending on template conditions
// @ts-ignore
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
/* eslint-disable */
{{>licenseInfo}}

import type { Configuration } from "./configuration";
import type { RequestArgs } from "./base";
import type { Configuration } from "./configuration{{importFileExtension}}";
import type { RequestArgs } from "./base{{importFileExtension}}";
import type { AxiosInstance, AxiosResponse } from 'axios';
import { RequiredError } from "./base";
import { RequiredError } from "./base{{importFileExtension}}";
{{#withNodeImports}}
import { URL, URLSearchParams } from 'url';
{{/withNodeImports}}
Expand Down Expand Up @@ -81,17 +81,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
/* eslint-disable */
{{>licenseInfo}}

export * from "./api";
export * from "./configuration";
{{#withSeparateModelsAndApi}}export * from "./{{tsModelPackage}}";{{/withSeparateModelsAndApi}}
export * from "./api{{importFileExtension}}";
export * from "./configuration{{importFileExtension}}";
{{#withSeparateModelsAndApi}}export * from "./{{tsModelPackage}}{{importFileExtension}}";{{/withSeparateModelsAndApi}}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
{{#withSeparateModelsAndApi}}{{#hasAllOf}}{{#allOf}}
// May contain unused imports in some cases
// @ts-ignore
import type { {{class}} } from './{{filename}}';{{/allOf}}{{/hasAllOf}}{{#hasOneOf}}{{#oneOf}}
import type { {{class}} } from './{{filename}}{{importFileExtension}}';{{/allOf}}{{/hasAllOf}}{{#hasOneOf}}{{#oneOf}}
// May contain unused imports in some cases
// @ts-ignore
import type { {{class}} } from './{{filename}}';{{/oneOf}}{{/hasOneOf}}{{^hasAllOf}}{{^hasOneOf}}{{#imports}}
import type { {{class}} } from './{{filename}}{{importFileExtension}}';{{/oneOf}}{{/hasOneOf}}{{^hasAllOf}}{{^hasOneOf}}{{#imports}}
// May contain unused imports in some cases
// @ts-ignore
import type { {{class}} } from './{{filename}}';{{/imports}}{{/hasOneOf}}{{/hasAllOf}}{{/withSeparateModelsAndApi}}
import type { {{class}} } from './{{filename}}{{importFileExtension}}';{{/imports}}{{/hasOneOf}}{{/hasAllOf}}{{/withSeparateModelsAndApi}}
{{#models}}{{#model}}
{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{#oneOf}}{{#-first}}{{>modelOneOf}}{{/-first}}{{/oneOf}}{{#allOf}}{{#-first}}{{>modelAllOf}}{{/-first}}{{/allOf}}{{^isEnum}}{{^oneOf}}{{^allOf}}{{>modelGeneric}}{{/allOf}}{{/oneOf}}{{/isEnum}}
{{/model}}{{/models}}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{{#models}}{{#model}}export * from './{{classFilename}}';{{/model}}
{{#models}}{{#model}}export * from './{{classFilename}}{{importFileExtension}}';{{/model}}
{{/models}}
8 changes: 4 additions & 4 deletions samples/client/echo_api/typescript-axios/build/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: an
if (typeof parameter === "object") {
if (Array.isArray(parameter)) {
(parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
}
}
else {
Object.keys(parameter).forEach(currentKey =>
Object.keys(parameter).forEach(currentKey =>
setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
);
}
}
}
else {
if (urlSearchParams.has(key)) {
urlSearchParams.append(key, parameter);
}
}
else {
urlSearchParams.set(key, parameter);
}
Expand Down
Loading
Loading