From bfc784e391d8c88ae92c414a3b2146f725fa9907 Mon Sep 17 00:00:00 2001 From: Kuzma <57258237+ksvirkou-hubspot@users.noreply.github.com> Date: Tue, 21 May 2024 14:31:05 +0300 Subject: [PATCH] [Typescript] Enum types (#18531) * Add enum type generator argument * Generate tests * fix default sample test * Fix all typescript tests * Update docs * Added description for enum types * Set enum type as default * Set addition param for all tests except --- .../typescript-consolidated-browser.yaml | 1 + bin/configs/typescript-consolidated-deno.yaml | 1 + .../typescript-consolidated-jquery.yaml | 1 + ...t-consolidated-node-object-parameters.yaml | 1 + docs/generators/typescript.md | 1 + .../languages/TypeScriptClientCodegen.java | 19 +++++++++++++++++++ .../resources/typescript/model/model.mustache | 14 ++++++++++++++ .../typescript/builds/browser/models/Order.ts | 6 +----- .../typescript/builds/browser/models/Pet.ts | 6 +----- .../typescript/builds/deno/models/Order.ts | 6 +----- .../typescript/builds/deno/models/Pet.ts | 6 +----- .../typescript/builds/jquery/models/Order.ts | 6 +----- .../typescript/builds/jquery/models/Pet.ts | 6 +----- .../builds/object_params/models/Order.ts | 6 +----- .../builds/object_params/models/Pet.ts | 6 +----- .../tests/browser/test/PetApi.test.ts | 4 ++-- .../test/models/ObjectSerializer.test.ts | 12 ++++++------ .../tests/deno/test/api/PetApi_test.ts | 2 +- .../tests/jquery/test/api/PetApi.test.ts | 2 +- .../object_params/test/api/PetApi.test.ts | 2 +- 20 files changed, 57 insertions(+), 51 deletions(-) diff --git a/bin/configs/typescript-consolidated-browser.yaml b/bin/configs/typescript-consolidated-browser.yaml index 8ea49d065b2..056c50b36d0 100644 --- a/bin/configs/typescript-consolidated-browser.yaml +++ b/bin/configs/typescript-consolidated-browser.yaml @@ -8,3 +8,4 @@ additionalProperties: projectName: ts-petstore-client moduleName: petstore supportsES6: true + enumType: stringUnion diff --git a/bin/configs/typescript-consolidated-deno.yaml b/bin/configs/typescript-consolidated-deno.yaml index b3317884609..eabb31a4291 100644 --- a/bin/configs/typescript-consolidated-deno.yaml +++ b/bin/configs/typescript-consolidated-deno.yaml @@ -7,3 +7,4 @@ additionalProperties: npmName: ts-petstore-client projectName: ts-petstore-client moduleName: petstore + enumType: stringUnion diff --git a/bin/configs/typescript-consolidated-jquery.yaml b/bin/configs/typescript-consolidated-jquery.yaml index 7e9669984c2..ceac9a204c9 100644 --- a/bin/configs/typescript-consolidated-jquery.yaml +++ b/bin/configs/typescript-consolidated-jquery.yaml @@ -7,3 +7,4 @@ additionalProperties: npmName: ts-petstore-client projectName: ts-petstore-client moduleName: petstore + enumType: stringUnion diff --git a/bin/configs/typescript-consolidated-node-object-parameters.yaml b/bin/configs/typescript-consolidated-node-object-parameters.yaml index 5e4e13a7ec7..d7f391bf5b0 100644 --- a/bin/configs/typescript-consolidated-node-object-parameters.yaml +++ b/bin/configs/typescript-consolidated-node-object-parameters.yaml @@ -8,3 +8,4 @@ additionalProperties: useObjectParameters: true projectName: ts-petstore-client moduleName: petstore + enumType: stringUnion diff --git a/docs/generators/typescript.md b/docs/generators/typescript.md index ed7612a0cea..d2c8464eca9 100644 --- a/docs/generators/typescript.md +++ b/docs/generators/typescript.md @@ -24,6 +24,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |enumNameSuffix|Suffix that will be appended to all enum names.| |Enum| |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| +|enumType|Specify the enum type which should be used in the client code.|
**stringUnion**
Union of literal string types
**enum**
Typescript's [string enums](https://www.typescriptlang.org/docs/handbook/enums.html#string-enums)
|enum| |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.|
**false**
No changes to the enum's are made, this is the default option.
**true**
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.
|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.|
**fetch-api**
fetch-api
**jquery**
jquery
|fetch-api| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java index 4e78a623b0e..e22cb70cdae 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java @@ -74,6 +74,9 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp private static final String USE_OBJECT_PARAMS_SWITCH = "useObjectParameters"; private static final String USE_OBJECT_PARAMS_DESC = "Use aggregate parameter objects as function arguments for api operations instead of passing each parameter as a separate function argument."; + private static final String ENUM_TYPE_SWITCH = "enumType"; + private static final String ENUM_TYPE_SWITCH_DESC = "Specify the enum type which should be used in the client code."; + private static final String[][] ENUM_TYPES = {{"stringUnion", "Union of literal string types"}, {"enum", "Typescript's [string enums](https://www.typescriptlang.org/docs/handbook/enums.html#string-enums)"}}; private final Map frameworkToHttpLibMap; @@ -135,6 +138,13 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp cliOptions.add(platformOption); + CliOption enumTypeOption = new CliOption(TypeScriptClientCodegen.ENUM_TYPE_SWITCH, TypeScriptClientCodegen.ENUM_TYPE_SWITCH_DESC); + for (String[] option : TypeScriptClientCodegen.ENUM_TYPES) { + enumTypeOption.addEnum(option[0], option[1]); + } + enumTypeOption.defaultValue(ENUM_TYPES[1][0]); + cliOptions.add(enumTypeOption); + // Set property naming to camelCase supportModelPropertyNaming(CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.camelCase); @@ -426,6 +436,15 @@ public class TypeScriptClientCodegen extends AbstractTypeScriptClientCodegen imp "http", httpLibName + ".ts" )); + additionalProperties.putIfAbsent(ENUM_TYPE_SWITCH, ENUM_TYPES[1][0]); + Object propEnumType = additionalProperties.get(ENUM_TYPE_SWITCH); + + Map enumTypes = new HashMap<>(); + for (String[] option : ENUM_TYPES) { + enumTypes.put(option[0], option[0].equals(propEnumType)); + } + additionalProperties.put("enumTypes", enumTypes); + Object propPlatform = additionalProperties.get(PLATFORM_SWITCH); if (propPlatform == null) { propPlatform = "browser"; diff --git a/modules/openapi-generator/src/main/resources/typescript/model/model.mustache b/modules/openapi-generator/src/main/resources/typescript/model/model.mustache index 798297cba06..33d22d33993 100644 --- a/modules/openapi-generator/src/main/resources/typescript/model/model.mustache +++ b/modules/openapi-generator/src/main/resources/typescript/model/model.mustache @@ -71,6 +71,8 @@ export class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{ {{#vars}} {{#isEnum}} +{{#enumTypes}} +{{#enum}} export enum {{classname}}{{enumName}} { {{#allowableValues}} {{#enumVars}} @@ -78,12 +80,19 @@ export enum {{classname}}{{enumName}} { {{/enumVars}} {{/allowableValues}} } +{{/enum}} +{{#stringUnion}} + export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}}; +{{/stringUnion}} +{{/enumTypes}} {{/isEnum}} {{/vars}} {{/hasEnums}} {{/isEnum}} {{#isEnum}} +{{#enumTypes}} +{{#enum}} export enum {{classname}} { {{#allowableValues}} {{#enumVars}} @@ -91,6 +100,11 @@ export enum {{classname}} { {{/enumVars}} {{/allowableValues}} } +{{/enum}} +{{#stringUnion}} + export type {{classname}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}}; +{{/stringUnion}} +{{/enumTypes}} {{/isEnum}} {{/model}} {{/models}} \ No newline at end of file diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts index 4d80550bb2a..4e9543bf72f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/Order.ts @@ -75,9 +75,5 @@ export class Order { } -export enum OrderStatusEnum { - Placed = 'placed', - Approved = 'approved', - Delivered = 'delivered' -} + export type OrderStatusEnum = "placed" | "approved" | "delivered" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts index ecaefffea4f..b52f8f669ef 100644 --- a/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/browser/models/Pet.ts @@ -77,9 +77,5 @@ export class Pet { } -export enum PetStatusEnum { - Available = 'available', - Pending = 'pending', - Sold = 'sold' -} + export type PetStatusEnum = "available" | "pending" | "sold" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts index 63e6b8fe3f1..de026e8068a 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/Order.ts @@ -75,9 +75,5 @@ export class Order { } -export enum OrderStatusEnum { - Placed = 'placed', - Approved = 'approved', - Delivered = 'delivered' -} + export type OrderStatusEnum = "placed" | "approved" | "delivered" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts index 1404661b6de..a028c692369 100644 --- a/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/deno/models/Pet.ts @@ -77,9 +77,5 @@ export class Pet { } -export enum PetStatusEnum { - Available = 'available', - Pending = 'pending', - Sold = 'sold' -} + export type PetStatusEnum = "available" | "pending" | "sold" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts index 4d80550bb2a..4e9543bf72f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Order.ts @@ -75,9 +75,5 @@ export class Order { } -export enum OrderStatusEnum { - Placed = 'placed', - Approved = 'approved', - Delivered = 'delivered' -} + export type OrderStatusEnum = "placed" | "approved" | "delivered" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts index ecaefffea4f..b52f8f669ef 100644 --- a/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/jquery/models/Pet.ts @@ -77,9 +77,5 @@ export class Pet { } -export enum PetStatusEnum { - Available = 'available', - Pending = 'pending', - Sold = 'sold' -} + export type PetStatusEnum = "available" | "pending" | "sold" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts index 4d80550bb2a..4e9543bf72f 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Order.ts @@ -75,9 +75,5 @@ export class Order { } -export enum OrderStatusEnum { - Placed = 'placed', - Approved = 'approved', - Delivered = 'delivered' -} + export type OrderStatusEnum = "placed" | "approved" | "delivered" ; diff --git a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts index ecaefffea4f..b52f8f669ef 100644 --- a/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts +++ b/samples/openapi3/client/petstore/typescript/builds/object_params/models/Pet.ts @@ -77,9 +77,5 @@ export class Pet { } -export enum PetStatusEnum { - Available = 'available', - Pending = 'pending', - Sold = 'sold' -} + export type PetStatusEnum = "available" | "pending" | "sold" ; diff --git a/samples/openapi3/client/petstore/typescript/tests/browser/test/PetApi.test.ts b/samples/openapi3/client/petstore/typescript/tests/browser/test/PetApi.test.ts index 88e0a850894..a4334fe7457 100644 --- a/samples/openapi3/client/petstore/typescript/tests/browser/test/PetApi.test.ts +++ b/samples/openapi3/client/petstore/typescript/tests/browser/test/PetApi.test.ts @@ -1,5 +1,5 @@ import { expect } from '@esm-bundle/chai'; -import { ServerConfiguration, createConfiguration, PetApi, Tag, Pet, PetStatusEnum, ApiException, RequiredError } from 'ts-petstore-client' +import { ServerConfiguration, createConfiguration, PetApi, Tag, Pet, ApiException, RequiredError } from 'ts-petstore-client' import image from "./pet"; const configuration = createConfiguration({ @@ -20,7 +20,7 @@ function createPet() { pet.id = Math.floor(Math.random() * 100000) pet.name = "PetName" pet.photoUrls = [] - pet.status = PetStatusEnum.Available + pet.status = 'available' pet.tags = [ tag ] return pet as Required; } diff --git a/samples/openapi3/client/petstore/typescript/tests/default/test/models/ObjectSerializer.test.ts b/samples/openapi3/client/petstore/typescript/tests/default/test/models/ObjectSerializer.test.ts index c0a2be85466..c152f5cdc6f 100644 --- a/samples/openapi3/client/petstore/typescript/tests/default/test/models/ObjectSerializer.test.ts +++ b/samples/openapi3/client/petstore/typescript/tests/default/test/models/ObjectSerializer.test.ts @@ -66,8 +66,8 @@ describe("ObjectSerializer", () => { }); it ("Enum", () => { - const input = "available" - expect(ObjectSerializer.serialize(input, "Pet.StatusEnum", "")).to.equal("available") + const input = petstore.PetStatusEnum.Available + expect(ObjectSerializer.serialize(input, "Pet.StatusEnum", "")).to.equal(petstore.PetStatusEnum.Available) }) it("Complex Class", () => { @@ -103,7 +103,7 @@ describe("ObjectSerializer", () => { "name": category.name }, "photoUrls": [ "url", "other url"], - "status": "available", + "status": petstore.PetStatusEnum.Available, "tags": tagResult }) }) @@ -173,8 +173,8 @@ describe("ObjectSerializer", () => { }); it ("Enum", () => { - const input = "available" - expect(ObjectSerializer.deserialize("available", "Pet.StatusEnum", "")).to.equal(input) + const input = petstore.PetStatusEnum.Available + expect(ObjectSerializer.deserialize(petstore.PetStatusEnum.Available, "Pet.StatusEnum", "")).to.equal(input) }) it("Complex Class", () => { @@ -210,7 +210,7 @@ describe("ObjectSerializer", () => { "name": category.name }, "photoUrls": [ "url", "other url"], - "status": "available", + "status": petstore.PetStatusEnum.Available, "tags": tagResult }, "Pet", "") as petstore.Pet diff --git a/samples/openapi3/client/petstore/typescript/tests/deno/test/api/PetApi_test.ts b/samples/openapi3/client/petstore/typescript/tests/deno/test/api/PetApi_test.ts index 9b8e652ce76..4025e670597 100644 --- a/samples/openapi3/client/petstore/typescript/tests/deno/test/api/PetApi_test.ts +++ b/samples/openapi3/client/petstore/typescript/tests/deno/test/api/PetApi_test.ts @@ -17,7 +17,7 @@ const petId = Math.floor(Math.random() * 100000); pet.id = petId; pet.name = "PetName"; pet.photoUrls = []; -pet.status = petstore.PetStatusEnum.Available; +pet.status = 'available'; pet.tags = [tag]; Deno.test({ diff --git a/samples/openapi3/client/petstore/typescript/tests/jquery/test/api/PetApi.test.ts b/samples/openapi3/client/petstore/typescript/tests/jquery/test/api/PetApi.test.ts index b061610023c..ef3882f9e57 100644 --- a/samples/openapi3/client/petstore/typescript/tests/jquery/test/api/PetApi.test.ts +++ b/samples/openapi3/client/petstore/typescript/tests/jquery/test/api/PetApi.test.ts @@ -16,7 +16,7 @@ const pet = new petstore.Pet() pet.id = Math.floor(Math.random() * 100000) pet.name = "PetName" pet.photoUrls = [] -pet.status = petstore.PetStatusEnum.Available +pet.status = 'available' pet.tags = [ tag ] QUnit.module("PetApi") diff --git a/samples/openapi3/client/petstore/typescript/tests/object_params/test/api/PetApi.test.ts b/samples/openapi3/client/petstore/typescript/tests/object_params/test/api/PetApi.test.ts index 2e2c311634d..302304492bb 100644 --- a/samples/openapi3/client/petstore/typescript/tests/object_params/test/api/PetApi.test.ts +++ b/samples/openapi3/client/petstore/typescript/tests/object_params/test/api/PetApi.test.ts @@ -15,7 +15,7 @@ const pet = new petstore.Pet() pet.id = Math.floor(Math.random() * 100000) pet.name = "PetName" pet.photoUrls = [] -pet.status = petstore.PetStatusEnum.Available +pet.status = 'available' pet.tags = [ tag ] describe("PetApi", () =>{