From 67db1cc1c1996c6ef870849c6c40a66c14520f3f Mon Sep 17 00:00:00 2001 From: Joe Turgeon Date: Wed, 10 Jul 2024 19:34:38 -0500 Subject: [PATCH 1/3] Adding enumType 'object' option that generates const and type definitions for enums to match Prisma Client. --- generator.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/generator.ts b/generator.ts index 6167695..8637b77 100755 --- a/generator.ts +++ b/generator.ts @@ -15,7 +15,7 @@ interface Config { typeSuffix: string; headerComment: string; modelType: "interface" | "type"; - enumType: "stringUnion" | "enum"; + enumType: "stringUnion" | "enum" | "object"; dateType: "Date" | "string" | "number"; bigIntType: "bigint" | "string" | "number"; decimalType: "Decimal" | "string" | "number"; @@ -52,7 +52,7 @@ function validateConfig(config: Config) { if (!["interface", "type"].includes(config.modelType)) { errors.push(`Invalid modelType: ${config.modelType}`); } - if (!["stringUnion", "enum"].includes(config.enumType)) { + if (!["stringUnion", "enum", "object"].includes(config.enumType)) { errors.push(`Invalid enumType: ${config.enumType}`); } if (!["Date", "string", "number"].includes(config.dateType)) { @@ -87,6 +87,11 @@ function getEnumTs( const enumValues = enumData.values.map(({ name }) => `"${name}"`).join(" | "); return `export type ${enumNameMap.get(enumData.name)} = ${enumValues};`; } + case "object": { + const enumValues = enumData.values.map(({ name }) => ` ${name}: "${name}"`).join(",\n"); + const enumName = enumNameMap.get(enumData.name); + return `export const ${enumName} = {\n${enumValues}\n};\n\nexport type ${enumName} = (typeof ${enumName})[keyof typeof ${enumName}];`; + } default: throw new Error(`Unknown enumType: ${config.enumType}`); } From 852021632211da8a13e7a779b45f83e0b63fa085 Mon Sep 17 00:00:00 2001 From: Joe Turgeon Date: Mon, 26 Aug 2024 15:20:46 -0500 Subject: [PATCH 2/3] Updating documentation for enumType option with new 'object' value. --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index aed8566..a6bdf88 100644 --- a/README.md +++ b/README.md @@ -46,25 +46,25 @@ Note that `bigint` types don't have a default `toJSON` method, so the above assu ## Options -| **Option** | **Type** | **Default** | **Description** | -| ----------------- | :----------------------------------------------------: | :------------------------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| output | `string` | `"interfaces.ts"` | The output location for the generated Typescript interfaces. | -| enumPrefix | `string` | `""` | Prefix to add to enum types. | -| enumSuffix | `string` | `""` | Suffix to add to enum types. | -| modelPrefix | `string` | `""` | Prefix to add to model types. | -| modelSuffix | `string` | `""` | Suffix to add to model types. | -| typePrefix | `string` | `""` | Prefix to add to [type](https://www.prisma.io/docs/concepts/components/prisma-schema/data-model#defining-composite-types) types (mongodb only). | -| typeSuffix | `string` | `""` | Suffix to add to [type](https://www.prisma.io/docs/concepts/components/prisma-schema/data-model#defining-composite-types) types (mongodb only). | -| headerComment | `string` | `"This file was auto-generated by prisma-generator-typescript-interfaces"` | Sets the header comment added to the top of the generated file. Set this to an empty string to disable the header comment. Supports multiple lines with `"\n"`. | -| modelType | `"interface" \| "type"` | `"interface"` | Controls how model definitions are generated. `"interface"` will create Typescript interfaces, `"type"` will create Typescript types. If using mongodb, this also affects `type` definitions. | -| enumType | `"stringUnion" \| "enum"` | `"stringUnion"` | Controls how enums are generated. `"enum"` will create Typescript enums, `"stringUnion"` will create union types with all the enum values. | -| dateType | `"Date" \| "string" \| "number"` | `"Date"` | The type to use for DateTime model fields. | -| bigIntType | `"bigint" \| "string" \| "number"` | `"bigint"` | The type to use for BigInt model fields. | -| decimalType | `"Decimal" \| "string" \| "number"` | `"Decimal"` | The type to use for Decimal model fields. The `Decimal` type here is just an interface with a `getValue()` function. You will need to cast to an actual Decimal type if you want to use other methods. | -| bytesType | `"Buffer" \| "BufferObject" \| "string" \| "number[]"` | `"Buffer"` | The type to use for Bytes model fields. `BufferObject` is a type definition which matches the output of `Buffer.toJSON()`, which is called when running `JSON.stringify()` on a Buffer. | -| optionalRelations | `boolean` | `true` | Controls whether model relation fields are optional. If `true`, all model relation fields will use `?:` in the field definition. | -| omitRelations | `boolean` | `false` | Controls whether model relation fields are omitted. If `true`, model definitions will not include their relations. | -| prettier | `boolean` | `false` | Formats the output using Prettier. Setting this to `true` requires that the `prettier` package is available. | +| **Option** | **Type** | **Default** | **Description** | +| ----------------- | :----------------------------------------------------: | :------------------------------------------------------------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| output | `string` | `"interfaces.ts"` | The output location for the generated Typescript interfaces. | +| enumPrefix | `string` | `""` | Prefix to add to enum types. | +| enumSuffix | `string` | `""` | Suffix to add to enum types. | +| modelPrefix | `string` | `""` | Prefix to add to model types. | +| modelSuffix | `string` | `""` | Suffix to add to model types. | +| typePrefix | `string` | `""` | Prefix to add to [type](https://www.prisma.io/docs/concepts/components/prisma-schema/data-model#defining-composite-types) types (mongodb only). | +| typeSuffix | `string` | `""` | Suffix to add to [type](https://www.prisma.io/docs/concepts/components/prisma-schema/data-model#defining-composite-types) types (mongodb only). | +| headerComment | `string` | `"This file was auto-generated by prisma-generator-typescript-interfaces"` | Sets the header comment added to the top of the generated file. Set this to an empty string to disable the header comment. Supports multiple lines with `"\n"`. | +| modelType | `"interface" \| "type"` | `"interface"` | Controls how model definitions are generated. `"interface"` will create Typescript interfaces, `"type"` will create Typescript types. If using mongodb, this also affects `type` definitions. | +| enumType | `"stringUnion" \| "enum" \| "object"` | `"stringUnion"` | Controls how enums are generated. `"object"` will create an object and type like Prisma client, `"enum"` will create TypeScript enums, `"stringUnion"` will create union types with all the enum values. | +| dateType | `"Date" \| "string" \| "number"` | `"Date"` | The type to use for DateTime model fields. | +| bigIntType | `"bigint" \| "string" \| "number"` | `"bigint"` | The type to use for BigInt model fields. | +| decimalType | `"Decimal" \| "string" \| "number"` | `"Decimal"` | The type to use for Decimal model fields. The `Decimal` type here is just an interface with a `getValue()` function. You will need to cast to an actual Decimal type if you want to use other methods. | +| bytesType | `"Buffer" \| "BufferObject" \| "string" \| "number[]"` | `"Buffer"` | The type to use for Bytes model fields. `BufferObject` is a type definition which matches the output of `Buffer.toJSON()`, which is called when running `JSON.stringify()` on a Buffer. | +| optionalRelations | `boolean` | `true` | Controls whether model relation fields are optional. If `true`, all model relation fields will use `?:` in the field definition. | +| omitRelations | `boolean` | `false` | Controls whether model relation fields are omitted. If `true`, model definitions will not include their relations. | +| prettier | `boolean` | `false` | Formats the output using Prettier. Setting this to `true` requires that the `prettier` package is available. | ## Example From af7b72d1282107d1ec8fdf71855412746b49a079 Mon Sep 17 00:00:00 2001 From: Joe Turgeon Date: Mon, 26 Aug 2024 15:24:18 -0500 Subject: [PATCH 3/3] Extending tests to verify enumType setting with 'object' value. --- .../expected/enumTypeObject.ts | 80 +++++++++++++++++++ tests/options-behavior/schema.prisma | 6 ++ 2 files changed, 86 insertions(+) create mode 100644 tests/options-behavior/expected/enumTypeObject.ts diff --git a/tests/options-behavior/expected/enumTypeObject.ts b/tests/options-behavior/expected/enumTypeObject.ts new file mode 100644 index 0000000..9756340 --- /dev/null +++ b/tests/options-behavior/expected/enumTypeObject.ts @@ -0,0 +1,80 @@ +// This file was auto-generated by prisma-generator-typescript-interfaces + +export const Gender = { + Male: "Male", + Female: "Female", + Other: "Other" +}; + +export type Gender = (typeof Gender)[keyof typeof Gender]; + +export const DataTest = { + Apple: "Apple", + Banana: "Banana", + Orange: "Orange", + Pear: "Pear" +}; + +export type DataTest = (typeof DataTest)[keyof typeof DataTest]; + +export interface Person { + id: number; + name: string; + age: number; + email: string | null; + gender: Gender; + addressId: number; + address?: Address; + friends?: Person[]; + friendsOf?: Person[]; + data?: Data | null; +} + +export interface Address { + id: number; + streetNumber: number; + streetName: string; + city: string; + isBilling: boolean; + people?: Person[]; +} + +export interface Data { + id: string; + stringField: string; + booleanField: boolean; + intField: number; + bigIntField: bigint; + floatField: number; + decimalField: Decimal; + dateField: Date; + jsonField: JsonValue; + bytesField: Buffer; + enumField: DataTest; + optionalStringField: string | null; + optionalBooleanField: boolean | null; + optionalIntField: number | null; + optionalBigIntField: bigint | null; + optionalFloatField: number | null; + optionalDecimalField: Decimal | null; + optionalDateField: Date | null; + optionalJsonField: JsonValue | null; + optionalBytesField: Buffer | null; + optionalEnumField: DataTest | null; + stringArrayField: string[]; + booleanArrayField: boolean[]; + intArrayField: number[]; + bigIntArrayField: bigint[]; + floatArrayField: number[]; + decimalArrayField: Decimal[]; + dateArrayField: Date[]; + jsonArrayField: JsonValue[]; + bytesArrayField: Buffer[]; + enumArrayField: DataTest[]; + personId: number; + person?: Person; +} + +type Decimal = { valueOf(): string }; + +type JsonValue = string | number | boolean | { [key in string]?: JsonValue } | Array | null; diff --git a/tests/options-behavior/schema.prisma b/tests/options-behavior/schema.prisma index 3468d1b..2f39f12 100644 --- a/tests/options-behavior/schema.prisma +++ b/tests/options-behavior/schema.prisma @@ -97,6 +97,12 @@ generator enumTypeSuffixPrefix { enumSuffix = "Enum" } +generator enumTypeObject { + provider = "node --loader ts-node/esm generator.ts" + output = "enumTypeObject.ts" + enumType = "object" +} + generator modelType { provider = "node --loader ts-node/esm generator.ts" output = "modelType.ts"