[typescript] Add importFileExtension option to support ECMAScript module resolution (#14371)

* Rename 'extensionForDeno' to 'importFileExtension'

* Add importFileExtension option to typescript generator

* Fix typo, update docs

* Update docstring
This commit is contained in:
Dan Michael O. Heggø
2023-01-03 17:45:49 +01:00
committed by GitHub
parent 38fdbe0c2c
commit 3dd313d35c
17 changed files with 67 additions and 62 deletions

View File

@@ -24,6 +24,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|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|
|fileContentDataType|Specifies the type to use for the content of a file - i.e. Blob (Browser, Deno) / Buffer (node)| |Buffer|
|framework|Specify the framework which should be used in the client code.|<dl><dt>**fetch-api**</dt><dd>fetch-api</dd><dt>**jquery**</dt><dd>jquery</dd></dl>|fetch-api|
|importFileExtension|File extension to use with relative imports. Set it to '.js' or '.mjs' when using [ESM](https://nodejs.org/api/esm.html). Defaults to '.ts' when 'platform' is set to 'deno'.| |null|
|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|
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |camelCase|
|npmName|The name under which you want to publish generated npm package. Required to generate a full package| |null|

View File

@@ -73,6 +73,8 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo
private static final String PLATFORM_SWITCH = "platform";
private static final String PLATFORM_SWITCH_DESC = "Specifies the platform the code should run on. The default is 'node' for the 'request' framework and 'browser' otherwise.";
private static final String[] PLATFORMS = { "browser", "node", "deno" };
private static final String IMPORT_FILE_EXTENSION_SWITCH = "importFileExtension";
private 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). Defaults to '.ts' when 'platform' is set to 'deno'.";
private static final String FILE_CONTENT_DATA_TYPE= "fileContentDataType";
private static final String FILE_CONTENT_DATA_TYPE_DESC = "Specifies the type to use for the content of a file - i.e. Blob (Browser, Deno) / Buffer (node)";
private static final String USE_RXJS_SWITCH = "useRxJS";
@@ -198,6 +200,7 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_RXJS_SWITCH, TypeScriptClientCodegen.USE_RXJS_SWITCH_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_OBJECT_PARAMS_SWITCH, TypeScriptClientCodegen.USE_OBJECT_PARAMS_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_INVERSIFY_SWITCH, TypeScriptClientCodegen.USE_INVERSIFY_SWITCH_DESC).defaultValue("false"));
cliOptions.add(new CliOption(TypeScriptClientCodegen.IMPORT_FILE_EXTENSION_SWITCH, TypeScriptClientCodegen.IMPORT_FILE_EXTENSION_SWITCH_DESC));
CliOption frameworkOption = new CliOption(TypeScriptClientCodegen.FRAMEWORK_SWITCH, TypeScriptClientCodegen.FRAMEWORK_SWITCH_DESC);
for (String option: TypeScriptClientCodegen.FRAMEWORKS) {
@@ -835,8 +838,9 @@ public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenCo
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
}
if ("deno".equals(propPlatform)) {
additionalProperties.put("extensionForDeno", ".ts");
Object fileExtension = additionalProperties.get(IMPORT_FILE_EXTENSION_SWITCH);
if (fileExtension == null && "deno".equals(propPlatform)) {
additionalProperties.put(IMPORT_FILE_EXTENSION_SWITCH, ".ts");
}
final boolean useRxJS = convertPropertyToBooleanAndWriteBack(USE_RXJS_SWITCH);

View File

@@ -1,24 +1,24 @@
// TODO: better import syntax?
import {BaseAPIRequestFactory, RequiredError, COLLECTION_FORMATS} from './baseapi{{extensionForDeno}}';
import {Configuration} from '../configuration{{extensionForDeno}}';
import {RequestContext, HttpMethod, ResponseContext, HttpFile} from '../http/http{{extensionForDeno}}';
import {BaseAPIRequestFactory, RequiredError, COLLECTION_FORMATS} from './baseapi{{importFileExtension}}';
import {Configuration} from '../configuration{{importFileExtension}}';
import {RequestContext, HttpMethod, ResponseContext, HttpFile} from '../http/http{{importFileExtension}}';
{{#platforms}}
{{#node}}
import {{^supportsES6}}* as{{/supportsES6}} FormData from "form-data";
import { URLSearchParams } from 'url';
{{/node}}
{{/platforms}}
import {ObjectSerializer} from '../models/ObjectSerializer{{extensionForDeno}}';
import {ApiException} from './exception{{extensionForDeno}}';
import {canConsumeForm, isCodeInRange} from '../util{{extensionForDeno}}';
import {SecurityAuthentication} from '../auth/auth{{extensionForDeno}}';
import {ObjectSerializer} from '../models/ObjectSerializer{{importFileExtension}}';
import {ApiException} from './exception{{importFileExtension}}';
import {canConsumeForm, isCodeInRange} from '../util{{importFileExtension}}';
import {SecurityAuthentication} from '../auth/auth{{importFileExtension}}';
{{#useInversify}}
import { injectable } from "inversify";
{{/useInversify}}
{{#imports}}
import { {{classname}} } from '{{filename}}{{extensionForDeno}}';
import { {{classname}} } from '{{filename}}{{importFileExtension}}';
{{/imports}}
{{#operations}}

View File

@@ -1,4 +1,4 @@
import { Configuration } from '../configuration{{extensionForDeno}}'
import { Configuration } from '../configuration{{importFileExtension}}'
{{#useInversify}}
import { injectable, inject } from "inversify";
import { AbstractConfiguration } from "../services/configuration";

View File

@@ -1,5 +1,5 @@
import {RequestContext, ResponseContext} from './http/http{{extensionForDeno}}';
import { Observable, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'./rxjsStub{{extensionForDeno}}'{{/useRxJS}};
import {RequestContext, ResponseContext} from './http/http{{importFileExtension}}';
import { Observable, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'./rxjsStub{{importFileExtension}}'{{/useRxJS}};
/**
* Defines the contract for a middleware intercepting requests before

View File

@@ -1,4 +1,4 @@
import { RequestContext } from "../http/http{{extensionForDeno}}";
import { RequestContext } from "../http/http{{importFileExtension}}";
{{#useInversify}}
import { injectable, inject, named } from "inversify";
import { AbstractTokenProvider } from "../services/configuration";

View File

@@ -1,15 +1,15 @@
import { HttpLibrary } from "./http/http{{extensionForDeno}}";
import { Middleware, PromiseMiddleware, PromiseMiddlewareWrapper } from "./middleware{{extensionForDeno}}";
import { HttpLibrary } from "./http/http{{importFileExtension}}";
import { Middleware, PromiseMiddleware, PromiseMiddlewareWrapper } from "./middleware{{importFileExtension}}";
{{#frameworks}}
{{#fetch-api}}
import { IsomorphicFetchHttpLibrary as DefaultHttpLibrary } from "./http/isomorphic-fetch{{extensionForDeno}}";
import { IsomorphicFetchHttpLibrary as DefaultHttpLibrary } from "./http/isomorphic-fetch{{importFileExtension}}";
{{/fetch-api}}
{{#jquery}}
import { JQueryHttpLibrary as DefaultHttpLibrary } from "./http/jquery";
{{/jquery}}
{{/frameworks}}
import { BaseServerConfiguration, server1 } from "./servers{{extensionForDeno}}";
import { configureAuthMethods, AuthMethods, AuthMethodsConfiguration } from "./auth/auth{{extensionForDeno}}";
import { BaseServerConfiguration, server1 } from "./servers{{importFileExtension}}";
import { configureAuthMethods, AuthMethods, AuthMethodsConfiguration } from "./auth/auth{{importFileExtension}}";
export interface Configuration {
readonly baseServer: BaseServerConfiguration;

View File

@@ -12,7 +12,7 @@ import * as https from 'https';
import {{^supportsES6}}* as{{/supportsES6}} URLParse from "url-parse";
{{/deno}}
{{/platforms}}
import { Observable, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{extensionForDeno}}'{{/useRxJS}};
import { Observable, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{importFileExtension}}'{{/useRxJS}};
{{#platforms}}
{{^deno}}

View File

@@ -1,5 +1,5 @@
import {HttpLibrary, RequestContext, ResponseContext} from './http{{extensionForDeno}}';
import { from, Observable } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{extensionForDeno}}'{{/useRxJS}};
import {HttpLibrary, RequestContext, ResponseContext} from './http{{importFileExtension}}';
import { from, Observable } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{importFileExtension}}'{{/useRxJS}};
{{#platforms}}
{{#node}}
import fetch from "node-fetch";

View File

@@ -1,4 +1,4 @@
import { RequestContext, HttpMethod } from "./http/http{{extensionForDeno}}";
import { RequestContext, HttpMethod } from "./http/http{{importFileExtension}}";
export interface BaseServerConfiguration {
makeRequestContext(endpoint: string, httpMethod: HttpMethod): RequestContext;

View File

@@ -1,41 +1,41 @@
export * from "./http/http{{extensionForDeno}}";
export * from "./auth/auth{{extensionForDeno}}";
export * from "./models/all{{extensionForDeno}}";
export { createConfiguration } from "./configuration{{extensionForDeno}}"
export{{#platforms}}{{#deno}} type{{/deno}}{{/platforms}} { Configuration } from "./configuration{{extensionForDeno}}"
export * from "./apis/exception{{extensionForDeno}}";
export * from "./servers{{extensionForDeno}}";
export { RequiredError } from "./apis/baseapi{{extensionForDeno}}";
export * from "./http/http{{importFileExtension}}";
export * from "./auth/auth{{importFileExtension}}";
export * from "./models/all{{importFileExtension}}";
export { createConfiguration } from "./configuration{{importFileExtension}}"
export{{#platforms}}{{#deno}} type{{/deno}}{{/platforms}} { Configuration } from "./configuration{{importFileExtension}}"
export * from "./apis/exception{{importFileExtension}}";
export * from "./servers{{importFileExtension}}";
export { RequiredError } from "./apis/baseapi{{importFileExtension}}";
{{#useRxJS}}
export { Middleware } from './middleware{{extensionForDeno}}';
export { Middleware } from './middleware{{importFileExtension}}';
{{/useRxJS}}
{{^useRxJS}}
export{{#platforms}}{{#deno}} type{{/deno}}{{/platforms}} { PromiseMiddleware as Middleware } from './middleware{{extensionForDeno}}';
export{{#platforms}}{{#deno}} type{{/deno}}{{/platforms}} { PromiseMiddleware as Middleware } from './middleware{{importFileExtension}}';
{{/useRxJS}}
{{#useObjectParameters}}
export { {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{classname}}{{operationIdCamelCase}}Request, {{/operation}}Object{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/ObjectParamAPI{{extensionForDeno}}';
export { {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{classname}}{{operationIdCamelCase}}Request, {{/operation}}Object{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/ObjectParamAPI{{importFileExtension}}';
{{/useObjectParameters}}
{{^useObjectParameters}}
{{#useRxJS}}
export { {{#apiInfo}}{{#apis}}{{#operations}}Observable{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/ObservableAPI{{extensionForDeno}}';
export { {{#apiInfo}}{{#apis}}{{#operations}}Observable{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/ObservableAPI{{importFileExtension}}';
{{/useRxJS}}
{{^useRxJS}}
export { {{#apiInfo}}{{#apis}}{{#operations}}Promise{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/PromiseAPI{{extensionForDeno}}';
export { {{#apiInfo}}{{#apis}}{{#operations}}Promise{{classname}} as {{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './types/PromiseAPI{{importFileExtension}}';
{{/useRxJS}}
{{/useObjectParameters}}
{{#useInversify}}
export * from "./services/index{{extensionForDeno}}";
export * from "./services/index{{importFileExtension}}";
{{#useObjectParameters}}
export { {{#apiInfo}}{{#apis}}{{#operations}}AbstractObject{{classname}} as Abstract{{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './services/ObjectParamAPI';
{{/useObjectParameters}}
{{^useObjectParameters}}
{{#useRxJS}}
export { {{#apiInfo}}{{#apis}}{{#operations}}AbstractObservable{{classname}} as Abstract{{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './services/ObservableAPI{{extensionForDeno}}';
export { {{#apiInfo}}{{#apis}}{{#operations}}AbstractObservable{{classname}} as Abstract{{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './services/ObservableAPI{{importFileExtension}}';
{{/useRxJS}}
{{^useRxJS}}
export { {{#apiInfo}}{{#apis}}{{#operations}}AbstractPromise{{classname}} as Abstract{{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './services/PromiseAPI{{extensionForDeno}}';
export { {{#apiInfo}}{{#apis}}{{#operations}}AbstractPromise{{classname}} as Abstract{{classname}}{{^-last}}, {{/-last}} {{/operations}}{{/apis}}{{/apiInfo}}} from './services/PromiseAPI{{importFileExtension}}';
{{/useRxJS}}
{{/useObjectParameters}}
{{/useInversify}}

View File

@@ -1,12 +1,12 @@
{{#models}}
{{#model}}
export * from '{{{ importPath }}}{{extensionForDeno}}';
export * from '{{{ importPath }}}{{importFileExtension}}';
{{/model}}
{{/models}}
{{#models}}
{{#model}}
import { {{classname}}{{#hasEnums}}{{#vars}}{{#isEnum}}, {{classname}}{{enumName}} {{/isEnum}} {{/vars}}{{/hasEnums}} } from '{{{ importPath }}}{{extensionForDeno}}';
import { {{classname}}{{#hasEnums}}{{#vars}}{{#isEnum}}, {{classname}}{{enumName}} {{/isEnum}} {{/vars}}{{/hasEnums}} } from '{{{ importPath }}}{{importFileExtension}}';
{{/model}}
{{/models}}

View File

@@ -2,9 +2,9 @@
{{#models}}
{{#model}}
{{#tsImports}}
import { {{classname}} } from '{{filename}}{{extensionForDeno}}';
import { {{classname}} } from '{{filename}}{{importFileExtension}}';
{{/tsImports}}
import { HttpFile } from '../http/http{{extensionForDeno}}';
import { HttpFile } from '../http/http{{importFileExtension}}';
{{#description}}
/**

View File

@@ -1,5 +1,5 @@
{{#models}}
{{#model}}
export * from '{{{ importPath }}}{{extensionForDeno}}'
export * from '{{{ importPath }}}{{importFileExtension}}'
{{/model}}
{{/models}}

View File

@@ -1,20 +1,20 @@
import { ResponseContext, RequestContext, HttpFile } from '../http/http{{extensionForDeno}}';
import { Configuration} from '../configuration{{extensionForDeno}}'
import { ResponseContext, RequestContext, HttpFile } from '../http/http{{importFileExtension}}';
import { Configuration} from '../configuration{{importFileExtension}}'
{{#useRxJS}}
import { Observable } from 'rxjs';
{{/useRxJS}}
{{#models}}
{{#model}}
import { {{{ classname }}} } from '{{{ importPath }}}{{extensionForDeno}}';
import { {{{ classname }}} } from '{{{ importPath }}}{{importFileExtension}}';
{{/model}}
{{/models}}
{{#apiInfo}}
{{#apis}}
{{#operations}}
import { Observable{{classname}} } from "./ObservableAPI{{extensionForDeno}}";
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}{{extensionForDeno}}";
import { Observable{{classname}} } from "./ObservableAPI{{importFileExtension}}";
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}{{importFileExtension}}";
{{#operation}}
export interface {{classname}}{{operationIdCamelCase}}Request {

View File

@@ -1,23 +1,23 @@
import { ResponseContext, RequestContext, HttpFile } from '../http/http{{extensionForDeno}}';
import { Configuration} from '../configuration{{extensionForDeno}}'
import { Observable, of, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{extensionForDeno}}'{{/useRxJS}};
import {mergeMap, map} from {{#useRxJS}}'rxjs/operators'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{extensionForDeno}}'{{/useRxJS}};
import { ResponseContext, RequestContext, HttpFile } from '../http/http{{importFileExtension}}';
import { Configuration} from '../configuration{{importFileExtension}}'
import { Observable, of, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{importFileExtension}}'{{/useRxJS}};
import {mergeMap, map} from {{#useRxJS}}'rxjs/operators'{{/useRxJS}}{{^useRxJS}}'../rxjsStub{{importFileExtension}}'{{/useRxJS}};
{{#useInversify}}
import { injectable, inject, optional } from "inversify";
import { AbstractConfiguration } from "../services/configuration{{extensionForDeno}}";
import { AbstractConfiguration } from "../services/configuration{{importFileExtension}}";
{{/useInversify}}
{{#models}}
{{#model}}
import { {{{ classname }}} } from '{{{ importPath }}}{{extensionForDeno}}';
import { {{{ classname }}} } from '{{{ importPath }}}{{importFileExtension}}';
{{/model}}
{{/models}}
{{#apiInfo}}
{{#apis}}
{{#operations}}
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}{{extensionForDeno}}";
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}{{importFileExtension}}";
{{#useInversify}}
import { Abstract{{classname}}RequestFactory, Abstract{{classname}}ResponseProcessor } from "../apis/{{classname}}.service{{extensionForDeno}}";
import { Abstract{{classname}}RequestFactory, Abstract{{classname}}ResponseProcessor } from "../apis/{{classname}}.service{{importFileExtension}}";
@injectable()
{{/useInversify}}

View File

@@ -1,5 +1,5 @@
import { ResponseContext, RequestContext, HttpFile } from '../http/http{{extensionForDeno}}';
import { Configuration} from '../configuration{{extensionForDeno}}'
import { ResponseContext, RequestContext, HttpFile } from '../http/http{{importFileExtension}}';
import { Configuration} from '../configuration{{importFileExtension}}'
{{#useInversify}}
import { injectable, inject, optional } from "inversify";
import { AbstractConfiguration } from "../services/configuration";
@@ -7,15 +7,15 @@ import { AbstractConfiguration } from "../services/configuration";
{{#models}}
{{#model}}
import { {{{ classname }}} } from '{{{ importPath }}}{{extensionForDeno}}';
import { {{{ classname }}} } from '{{{ importPath }}}{{importFileExtension}}';
{{/model}}
{{/models}}
{{#apiInfo}}
{{#apis}}
import { Observable{{classname}} } from './ObservableAPI{{extensionForDeno}}';
import { Observable{{classname}} } from './ObservableAPI{{importFileExtension}}';
{{#operations}}
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}{{extensionForDeno}}";
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}{{importFileExtension}}";
{{#useInversify}}
import { Abstract{{classname}}RequestFactory, Abstract{{classname}}ResponseProcessor } from "../apis/{{classname}}.service";