[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
This commit is contained in:
Kuzma 2024-05-21 14:31:05 +03:00 committed by GitHub
parent c289982848
commit bfc784e391
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 57 additions and 51 deletions

View File

@ -8,3 +8,4 @@ additionalProperties:
projectName: ts-petstore-client
moduleName: petstore
supportsES6: true
enumType: stringUnion

View File

@ -7,3 +7,4 @@ additionalProperties:
npmName: ts-petstore-client
projectName: ts-petstore-client
moduleName: petstore
enumType: stringUnion

View File

@ -7,3 +7,4 @@ additionalProperties:
npmName: ts-petstore-client
projectName: ts-petstore-client
moduleName: petstore
enumType: stringUnion

View File

@ -8,3 +8,4 @@ additionalProperties:
useObjectParameters: true
projectName: ts-petstore-client
moduleName: petstore
enumType: stringUnion

View File

@ -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.|<dl><dt>**stringUnion**</dt><dd>Union of literal string types</dd><dt>**enum**</dt><dd>Typescript's [string enums](https://www.typescriptlang.org/docs/handbook/enums.html#string-enums)</dd></dl>|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.|<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|

View File

@ -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<String, String> 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<String, Boolean> 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";

View File

@ -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}}

View File

@ -75,9 +75,5 @@ export class Order {
}
export enum OrderStatusEnum {
Placed = 'placed',
Approved = 'approved',
Delivered = 'delivered'
}
export type OrderStatusEnum = "placed" | "approved" | "delivered" ;

View File

@ -77,9 +77,5 @@ export class Pet {
}
export enum PetStatusEnum {
Available = 'available',
Pending = 'pending',
Sold = 'sold'
}
export type PetStatusEnum = "available" | "pending" | "sold" ;

View File

@ -75,9 +75,5 @@ export class Order {
}
export enum OrderStatusEnum {
Placed = 'placed',
Approved = 'approved',
Delivered = 'delivered'
}
export type OrderStatusEnum = "placed" | "approved" | "delivered" ;

View File

@ -77,9 +77,5 @@ export class Pet {
}
export enum PetStatusEnum {
Available = 'available',
Pending = 'pending',
Sold = 'sold'
}
export type PetStatusEnum = "available" | "pending" | "sold" ;

View File

@ -75,9 +75,5 @@ export class Order {
}
export enum OrderStatusEnum {
Placed = 'placed',
Approved = 'approved',
Delivered = 'delivered'
}
export type OrderStatusEnum = "placed" | "approved" | "delivered" ;

View File

@ -77,9 +77,5 @@ export class Pet {
}
export enum PetStatusEnum {
Available = 'available',
Pending = 'pending',
Sold = 'sold'
}
export type PetStatusEnum = "available" | "pending" | "sold" ;

View File

@ -75,9 +75,5 @@ export class Order {
}
export enum OrderStatusEnum {
Placed = 'placed',
Approved = 'approved',
Delivered = 'delivered'
}
export type OrderStatusEnum = "placed" | "approved" | "delivered" ;

View File

@ -77,9 +77,5 @@ export class Pet {
}
export enum PetStatusEnum {
Available = 'available',
Pending = 'pending',
Sold = 'sold'
}
export type PetStatusEnum = "available" | "pending" | "sold" ;

View File

@ -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<Pet>;
}

View File

@ -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

View File

@ -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({

View File

@ -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")

View File

@ -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", () =>{