diff --git a/packages/apollo/tests/code-first/app.module.ts b/packages/apollo/tests/code-first/app.module.ts index a5586e455..cb1df6f62 100644 --- a/packages/apollo/tests/code-first/app.module.ts +++ b/packages/apollo/tests/code-first/app.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriverConfig } from '../../lib'; import { ApolloDriver } from '../../lib/drivers'; +import { CatsModule } from './cats/cats.module'; import { DirectionsModule } from './directions/directions.module'; import { RecipesModule } from './recipes/recipes.module'; @@ -9,6 +10,7 @@ import { RecipesModule } from './recipes/recipes.module'; imports: [ RecipesModule, DirectionsModule, + CatsModule, GraphQLModule.forRoot({ driver: ApolloDriver, debug: false, diff --git a/packages/apollo/tests/code-first/cats/cats.resolver.ts b/packages/apollo/tests/code-first/cats/cats.resolver.ts index 8bfd7dcaf..95cf34c83 100644 --- a/packages/apollo/tests/code-first/cats/cats.resolver.ts +++ b/packages/apollo/tests/code-first/cats/cats.resolver.ts @@ -1,4 +1,5 @@ -import { Query, Resolver } from '@nestjs/graphql'; +import { Args, Query, Resolver } from '@nestjs/graphql'; +import { CatType } from '../enums/cat-type.enum'; @Resolver() export class CatsResolver { @@ -6,4 +7,12 @@ export class CatsResolver { getAnimalName(): string { return 'cat'; } + + @Query((returns) => CatType) + catType( + @Args({ name: 'catType', type: () => CatType }) + catType: CatType, + ): CatType { + return catType; + } } diff --git a/packages/apollo/tests/code-first/enums/cat-type.enum.ts b/packages/apollo/tests/code-first/enums/cat-type.enum.ts new file mode 100644 index 000000000..8f2fda287 --- /dev/null +++ b/packages/apollo/tests/code-first/enums/cat-type.enum.ts @@ -0,0 +1,16 @@ +import { registerEnumType } from '@nestjs/graphql'; + +export enum CatType { + PersianCat = 'persian-cat', + MaineCoon = 'maine-coon', + Ragdoll = 'ragdoll', + SomeNewAwesomeCat = 'some-new-awesome-cat', + SomeWEIRDCat = 'some-weird-cat', + anotherAwesomeCat = 'another-awesome-cat', +} + +registerEnumType(CatType, { + name: 'CatType', + description: 'Distinguish cats', + mapToUppercase: true, +}); diff --git a/packages/apollo/tests/e2e/code-first-schema.spec.ts b/packages/apollo/tests/e2e/code-first-schema.spec.ts index 3b337bb57..7a8e601da 100644 --- a/packages/apollo/tests/e2e/code-first-schema.spec.ts +++ b/packages/apollo/tests/e2e/code-first-schema.spec.ts @@ -20,6 +20,7 @@ import { SampleOrphanedType } from '../code-first/other/sample-orphaned.type'; import { IRecipesResolver } from '../code-first/recipes/irecipes.resolver'; import { Recipe } from '../code-first/recipes/models/recipe'; import { RecipesResolver } from '../code-first/recipes/recipes.resolver'; +import { CatsResolver } from '../code-first/cats/cats.resolver'; import { getMutation, getMutationByName, @@ -50,6 +51,7 @@ describe('Code-first - schema factory', () => { [ RecipesResolver, DirectionsResolver, + CatsResolver, AbstractResolver, IRecipesResolver, ], @@ -68,10 +70,10 @@ describe('Code-first - schema factory', () => { printedSchemaSnapshot, ); }); - it('should define 5 queries', async () => { + it('should define 7 queries', async () => { const type = getQuery(introspectionSchema); - expect(type.fields.length).toEqual(5); + expect(type.fields.length).toEqual(7); expect(type.fields.map((item) => item.name)).toEqual( expect.arrayContaining([ 'recipes', @@ -79,6 +81,7 @@ describe('Code-first - schema factory', () => { 'categories', 'move', 'recipe', + 'catType', ]), ); }); @@ -154,6 +157,58 @@ describe('Code-first - schema factory', () => { ); }); + it('should define "CatType" enum to use CAPITALIZED_UNDERSCORE', () => { + const type = introspectionSchema.types.find( + ({ name }) => name === 'CatType', + ); + + expect(type).toEqual( + expect.objectContaining({ + kind: TypeKind.ENUM, + name: 'CatType', + description: 'Distinguish cats', + enumValues: [ + { + deprecationReason: null, + description: null, + isDeprecated: false, + name: 'PERSIAN_CAT', + }, + { + deprecationReason: null, + description: null, + isDeprecated: false, + name: 'MAINE_COON', + }, + { + deprecationReason: null, + description: null, + isDeprecated: false, + name: 'RAGDOLL', + }, + { + deprecationReason: null, + description: null, + isDeprecated: false, + name: 'SOME_NEW_AWESOME_CAT', + }, + { + deprecationReason: null, + description: null, + isDeprecated: false, + name: 'SOME_WEIRD_CAT', + }, + { + deprecationReason: null, + description: null, + isDeprecated: false, + name: 'ANOTHER_AWESOME_CAT', + }, + ], + }), + ); + }); + it('should define "SearchResultUnion" union', () => { const type = introspectionSchema.types.find( ({ name }) => name === 'SearchResultUnion', diff --git a/packages/apollo/tests/graphql/sort-auto-schema.module.ts b/packages/apollo/tests/graphql/sort-auto-schema.module.ts index 5e2d74c95..ff0ff0b7a 100644 --- a/packages/apollo/tests/graphql/sort-auto-schema.module.ts +++ b/packages/apollo/tests/graphql/sort-auto-schema.module.ts @@ -3,11 +3,13 @@ import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver } from '../../lib/drivers'; import { DirectionsModule } from '../code-first/directions/directions.module'; import { RecipesModule } from '../code-first/recipes/recipes.module'; +import { CatsModule } from '../code-first/cats/cats.module'; @Module({ imports: [ RecipesModule, DirectionsModule, + CatsModule.register('useClass'), GraphQLModule.forRoot({ driver: ApolloDriver, autoSchemaFile: 'schema.graphql', diff --git a/packages/apollo/tests/graphql/transform-auto-schema-file.module.ts b/packages/apollo/tests/graphql/transform-auto-schema-file.module.ts index 63931344a..923de0cce 100644 --- a/packages/apollo/tests/graphql/transform-auto-schema-file.module.ts +++ b/packages/apollo/tests/graphql/transform-auto-schema-file.module.ts @@ -4,11 +4,13 @@ import { GraphQLSchema, lexicographicSortSchema } from 'graphql'; import { ApolloDriver } from '../../lib/drivers'; import { DirectionsModule } from '../code-first/directions/directions.module'; import { RecipesModule } from '../code-first/recipes/recipes.module'; +import { CatsModule } from '../code-first/cats/cats.module'; @Module({ imports: [ RecipesModule, DirectionsModule, + CatsModule.register('useClass'), GraphQLModule.forRoot({ driver: ApolloDriver, autoSchemaFile: 'schema.graphql', diff --git a/packages/apollo/tests/utils/printed-schema.snapshot.ts b/packages/apollo/tests/utils/printed-schema.snapshot.ts index d851c5dc7..bff3ba0fb 100644 --- a/packages/apollo/tests/utils/printed-schema.snapshot.ts +++ b/packages/apollo/tests/utils/printed-schema.snapshot.ts @@ -75,6 +75,8 @@ type Query { take: Int = 25 ): [Recipe!]! move(direction: Direction!): Direction! + getAnimalName: String! + catType(catType: CatType!): CatType! } """Search result description""" @@ -90,6 +92,16 @@ enum Direction { Sideways @deprecated(reason: "Replaced with Left or Right") } +"""Distinguish cats""" +enum CatType { + PERSIAN_CAT + MAINE_COON + RAGDOLL + SOME_NEW_AWESOME_CAT + SOME_WEIRD_CAT + ANOTHER_AWESOME_CAT +} + type Mutation { addRecipe(newRecipeData: NewRecipeInput!): Recipe! removeRecipe(id: String!): Boolean! @@ -113,6 +125,16 @@ export const sortedPrintedSchemaSnapshot = `# ---------------------------------- # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) # ------------------------------------------------------ +"""Distinguish cats""" +enum CatType { + ANOTHER_AWESOME_CAT + MAINE_COON + PERSIAN_CAT + RAGDOLL + SOME_NEW_AWESOME_CAT + SOME_WEIRD_CAT +} + type Category { description: String! name: String! @@ -162,7 +184,9 @@ input NewRecipeInput { } type Query { + catType(catType: CatType!): CatType! categories: [Category!]! + getAnimalName: String! move(direction: Direction!): Direction! """get recipe by id""" diff --git a/packages/graphql/lib/schema-builder/factories/enum-definition.factory.ts b/packages/graphql/lib/schema-builder/factories/enum-definition.factory.ts index e2c22b2b8..d6993db65 100644 --- a/packages/graphql/lib/schema-builder/factories/enum-definition.factory.ts +++ b/packages/graphql/lib/schema-builder/factories/enum-definition.factory.ts @@ -1,7 +1,11 @@ +import { upperCase } from 'lodash'; import { Injectable } from '@nestjs/common'; import { GraphQLEnumType } from 'graphql'; import { EnumMetadata } from '../metadata'; +export const mapToUppercase = (value: string): string => + upperCase(value).replaceAll(' ', '_'); + export interface EnumDefinition { enumRef: object; type: GraphQLEnumType; @@ -19,7 +23,13 @@ export class EnumDefinitionFactory { description: metadata.description, values: Object.keys(enumValues).reduce((prevValue, key) => { const valueMap = metadata.valuesMap[key]; - prevValue[key] = { + + let enumKey = key; + if (metadata.mapToUppercase) { + enumKey = mapToUppercase(key); + } + + prevValue[enumKey] = { value: enumValues[key], description: valueMap?.description, deprecationReason: valueMap?.deprecationReason, diff --git a/packages/graphql/lib/schema-builder/metadata/enum.metadata.ts b/packages/graphql/lib/schema-builder/metadata/enum.metadata.ts index ea05f820c..182cacdd9 100644 --- a/packages/graphql/lib/schema-builder/metadata/enum.metadata.ts +++ b/packages/graphql/lib/schema-builder/metadata/enum.metadata.ts @@ -12,4 +12,5 @@ export interface EnumMetadata { name: string; description?: string; valuesMap?: EnumMetadataValuesMap; + mapToUppercase?: boolean; } diff --git a/packages/graphql/lib/type-factories/register-enum-type.factory.ts b/packages/graphql/lib/type-factories/register-enum-type.factory.ts index fc361539b..e4c07c0b7 100644 --- a/packages/graphql/lib/type-factories/register-enum-type.factory.ts +++ b/packages/graphql/lib/type-factories/register-enum-type.factory.ts @@ -25,6 +25,12 @@ export interface EnumOptions { * A map of options for the values of the enum. */ valuesMap?: EnumMetadataValuesMap; + + /** + * Automatically map enum to UPPER_CASE in the schema. + * Defaults to `false` + */ + mapToUppercase?: boolean; } /** @@ -41,6 +47,7 @@ export function registerEnumType( name: options.name, description: options.description, valuesMap: options.valuesMap || {}, + mapToUppercase: options.mapToUppercase || false, }), ); }