From 0e3af17b129d9f92b151df9cba05c12c30d9e6ef Mon Sep 17 00:00:00 2001 From: KunoichiZ Date: Sat, 7 Dec 2024 20:30:20 -0600 Subject: [PATCH] feat: add natures --- README.md | 1 + graphql/enums.graphql | 29 ++ graphql/resolvers.graphql | 21 ++ graphql/schema.graphql | 21 ++ src/lib/assets/natures.ts | 256 ++++++++++++++++++ src/lib/assets/pokemon-source.ts | 12 + src/lib/mappers/natureMapper.ts | 21 ++ src/lib/resolvers/RootResolver.ts | 7 + src/lib/resolvers/natureResolver.ts | 54 ++++ src/lib/types/graphql-mapped-types.ts | 14 + src/lib/validations/getNatureArgs.ts | 56 ++++ tests/scenarios/natures/getAllNatures.test.ts | 204 ++++++++++++++ tests/scenarios/natures/getNature.test.ts | 46 ++++ tests/testUtils/queries/natures.ts | 30 ++ tests/testUtils/types.d.ts | 12 +- 15 files changed, 783 insertions(+), 1 deletion(-) create mode 100644 src/lib/assets/natures.ts create mode 100644 src/lib/mappers/natureMapper.ts create mode 100644 src/lib/resolvers/natureResolver.ts create mode 100644 src/lib/validations/getNatureArgs.ts create mode 100644 tests/scenarios/natures/getAllNatures.test.ts create mode 100644 tests/scenarios/natures/getNature.test.ts create mode 100644 tests/testUtils/queries/natures.ts diff --git a/README.md b/README.md index 97d4cc941c..234d573069 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ and [Bulbapedia]. - Moves - Learnsets - Type matchups + - Natures ## JavaScript Companion Library diff --git a/graphql/enums.graphql b/graphql/enums.graphql index a1fdec29bc..d51a92ca31 100644 --- a/graphql/enums.graphql +++ b/graphql/enums.graphql @@ -3502,3 +3502,32 @@ enum IsNonStandard { "When set the move can exclusively be used Pokémon Sword and Pokémon Shield as it requires Gigantamaxing your Pokémon." Gigantamax } + +"The Natures in Pokémon" +enum NaturesEnum { + adamant + bashful + bold + brave + calm + careful + docile + gentle + hardy + hasty + impish + jolly + lax + lonely + mild + modest + naive + naughty + quiet + quirky + rash + relaxed + sassy + serious + timid +} diff --git a/graphql/resolvers.graphql b/graphql/resolvers.graphql index 38794ff95f..6a6b220495 100644 --- a/graphql/resolvers.graphql +++ b/graphql/resolvers.graphql @@ -223,4 +223,25 @@ type Query { "Gets the type matchup data for the given type or types" getTypeMatchup("The primary type to check" primaryType: TypesEnum!, "The secondary type to check" secondaryType: TypesEnum): TypeMatchup! + + "Gets the details of a specific Nature" + getNature("The nature to look up" nature: NaturesEnum!): Nature! + + """ + Returns a list of all the Natures in Pokémon. + + For every Nature all the data on each requested field is returned. + + You can provide `take` to limit the amount of Pokémon to return (default: 1), set the offset of where to start with `offset`, and reverse the entire array with `reverse`. + """ + getAllNatures( + "Sets the offset where to start" + offset: Int = 0 + + "Return only this many results, starting from the offset" + take: Int = 1 + + "Reverses the dataset before paginating" + reverse: Boolean = false + ): [Nature!]! } diff --git a/graphql/schema.graphql b/graphql/schema.graphql index 931bcf271b..4bfbc16913 100644 --- a/graphql/schema.graphql +++ b/graphql/schema.graphql @@ -496,3 +496,24 @@ type TypeEffectiveness { "The types with 0.5x effectiveness" resistedTypes: [String!]! } + +"A single Nature entry" +type Nature { + "The key of the nature as stored in the API" + key: NaturesEnum! + + "The name of a nature" + name: String! + + "The stat the nature increases by 10%" + increasedStat: String + + "The stat the nature decreases by 10%" + decreasedStat: String + + "The flavor of food the nature prefers" + preferredFlavor: String + + "The flavor of food the nature dislikes" + dislikedFlavor: String +} diff --git a/src/lib/assets/natures.ts b/src/lib/assets/natures.ts new file mode 100644 index 0000000000..c5504e026d --- /dev/null +++ b/src/lib/assets/natures.ts @@ -0,0 +1,256 @@ +import type { PokemonTypes } from '#assets/pokemon-source'; +import { Collection } from '@discordjs/collection'; + +/** The natures in Pokémon */ +export const natures = new Collection([ + [ + 'adamant', + { + name: 'Adamant', + increasedStat: 'Attack', + decreasedStat: 'Special Attack', + preferredFlavor: 'Spicy', + dislikedFlavor: 'Dry' + } + ], + [ + 'bashful', + { + name: 'Bashful', + increasedStat: null, + decreasedStat: null, + preferredFlavor: null, + dislikedFlavor: null + } + ], + [ + 'bold', + { + name: 'Bold', + increasedStat: 'Defense', + decreasedStat: 'Attack', + preferredFlavor: 'Sour', + dislikedFlavor: 'Spicy' + } + ], + [ + 'brave', + { + name: 'Brave', + increasedStat: 'Attack', + decreasedStat: 'Speed', + preferredFlavor: 'Spicy', + dislikedFlavor: 'Sweet' + } + ], + [ + 'calm', + { + name: 'Calm', + increasedStat: 'Special Defense', + decreasedStat: 'Attack', + preferredFlavor: 'Bitter', + dislikedFlavor: 'Spicy' + } + ], + [ + 'careful', + { + name: 'Careful', + increasedStat: 'Special Defense', + decreasedStat: 'Special Attack', + preferredFlavor: 'Bitter', + dislikedFlavor: 'Dry' + } + ], + [ + 'docile', + { + name: 'Docile', + increasedStat: null, + decreasedStat: null, + preferredFlavor: null, + dislikedFlavor: null + } + ], + [ + 'gentle', + { + name: 'Gentle', + increasedStat: 'Special Defense', + decreasedStat: 'Defense', + preferredFlavor: 'Bitter', + dislikedFlavor: 'Sour' + } + ], + [ + 'hardy', + { + name: 'Hardy', + increasedStat: null, + decreasedStat: null, + preferredFlavor: null, + dislikedFlavor: null + } + ], + [ + 'hasty', + { + name: 'Hasty', + increasedStat: 'Hasty', + decreasedStat: 'Defense', + preferredFlavor: 'Sweet', + dislikedFlavor: 'Sour' + } + ], + [ + 'impish', + { + name: 'Impish', + increasedStat: 'Defense', + decreasedStat: 'Sour', + preferredFlavor: 'Special Attack', + dislikedFlavor: 'Dry' + } + ], + [ + 'jolly', + { + name: 'Jolly', + increasedStat: 'Speed', + decreasedStat: 'Special Attack', + preferredFlavor: 'Sweet', + dislikedFlavor: 'Dry' + } + ], + [ + 'lax', + { + name: 'Lax', + increasedStat: 'Defense', + decreasedStat: 'Sour', + preferredFlavor: 'Special Defense', + dislikedFlavor: 'Bitter' + } + ], + [ + 'lonely', + { + name: 'Lonely', + increasedStat: 'Attack', + decreasedStat: 'Defense', + preferredFlavor: 'Spicy', + dislikedFlavor: 'Sour' + } + ], + [ + 'mild', + { + name: 'Mild', + increasedStat: 'Special Attack', + decreasedStat: 'Defense', + preferredFlavor: 'Dry', + dislikedFlavor: 'Sour' + } + ], + [ + 'modest', + { + name: 'Modest', + increasedStat: 'Special Attack', + decreasedStat: 'Attack', + preferredFlavor: 'Dry', + dislikedFlavor: 'Spicy' + } + ], + [ + 'naive', + { + name: 'Naive', + increasedStat: 'Speed', + decreasedStat: 'Special Defense', + preferredFlavor: 'Sweet', + dislikedFlavor: 'Bitter' + } + ], + [ + 'naughty', + { + name: 'Naughty', + increasedStat: 'Attack', + decreasedStat: 'Special Defense', + preferredFlavor: 'Spicy', + dislikedFlavor: 'Bitter' + } + ], + [ + 'quiet', + { + name: 'Quiet', + increasedStat: 'Special Attack', + decreasedStat: 'Speed', + preferredFlavor: 'Dry', + dislikedFlavor: 'Sweet' + } + ], + [ + 'quirky', + { + name: 'Quirky', + increasedStat: null, + decreasedStat: null, + preferredFlavor: null, + dislikedFlavor: null + } + ], + [ + 'rash', + { + name: 'Rash', + increasedStat: 'Special Attack', + decreasedStat: 'Special Defense', + preferredFlavor: 'Dry', + dislikedFlavor: 'Bitter' + } + ], + [ + 'relaxed', + { + name: 'Relaxed', + increasedStat: 'Defense', + decreasedStat: 'Speed', + preferredFlavor: 'Sour', + dislikedFlavor: 'Sweet' + } + ], + [ + 'sassy', + { + name: 'Sassy', + increasedStat: 'Special Defense', + decreasedStat: 'Speed', + preferredFlavor: 'Bitter', + dislikedFlavor: 'Sweet' + } + ], + [ + 'serious', + { + name: 'Serious', + increasedStat: null, + decreasedStat: null, + preferredFlavor: null, + dislikedFlavor: null + } + ], + [ + 'timid', + { + name: 'Timid', + increasedStat: 'Speed', + decreasedStat: 'Attack', + preferredFlavor: 'Sweet', + dislikedFlavor: 'Spicy' + } + ] +]); diff --git a/src/lib/assets/pokemon-source.ts b/src/lib/assets/pokemon-source.ts index 393fb2e8fa..61c1bb51f2 100644 --- a/src/lib/assets/pokemon-source.ts +++ b/src/lib/assets/pokemon-source.ts @@ -287,4 +287,16 @@ export namespace PokemonTypes { | "Ally's Side" | 'Normal' | 'All'; + + export interface Natures { + name: string; + + increasedStat: string | null; + + decreasedStat: string | null; + + preferredFlavor: string | null; + + dislikedFlavor: string | null; + } } diff --git a/src/lib/mappers/natureMapper.ts b/src/lib/mappers/natureMapper.ts new file mode 100644 index 0000000000..bf11960e31 --- /dev/null +++ b/src/lib/mappers/natureMapper.ts @@ -0,0 +1,21 @@ +import type { PokemonTypes } from '#assets/pokemon-source'; +import type { Nature } from '#types/graphql-mapped-types'; +import type { GraphQLSet } from '#utils/GraphQLSet'; +import { addPropertyToObjectFieldBased } from '#utils/addPropertyToObject'; + +export function mapNatureDataToNatureGraphQL({ data, requestedFields }: MapNatureDataToNatureGraphQLParameters): Nature { + const natureObject: Nature = {} as Nature; + + addPropertyToObjectFieldBased({ objectTarget: natureObject, propertyKey: 'name', propertyValue: data.name, requestedFields }); + addPropertyToObjectFieldBased({ objectTarget: natureObject, propertyKey: 'increasedStat', propertyValue: data.increasedStat, requestedFields }); + addPropertyToObjectFieldBased({ objectTarget: natureObject, propertyKey: 'decreasedStat', propertyValue: data.decreasedStat, requestedFields }); + addPropertyToObjectFieldBased({ objectTarget: natureObject, propertyKey: 'preferredFlavor', propertyValue: data.preferredFlavor, requestedFields }); + addPropertyToObjectFieldBased({ objectTarget: natureObject, propertyKey: 'dislikedFlavor', propertyValue: data.dislikedFlavor, requestedFields }); + + return natureObject; +} + +interface MapNatureDataToNatureGraphQLParameters { + data: PokemonTypes.Natures; + requestedFields: GraphQLSet; +} diff --git a/src/lib/resolvers/RootResolver.ts b/src/lib/resolvers/RootResolver.ts index ec64bc47ff..6db14e96cc 100644 --- a/src/lib/resolvers/RootResolver.ts +++ b/src/lib/resolvers/RootResolver.ts @@ -4,6 +4,7 @@ import { getFuzzyLearnset, getLearnset } from '#resolvers/learnsetResolvers'; import { getFuzzyMove, getMove } from '#resolvers/moveResolvers'; import { getAllPokemon, getFuzzyPokemon, getPokemon, getPokemonByDexNumber } from '#resolvers/pokemonResolvers'; import { getTypeMatchup } from '#resolvers/typeResolver'; +import { getNature, getAllNatures } from '#resolvers/natureResolver'; import { graphqlResolveInfoToRequestedFields } from '#utils/getRequestedFields'; import type { IExecutableSchemaDefinition } from '@graphql-tools/schema'; @@ -47,6 +48,12 @@ export const RootResolver: IExecutableSchemaDefinition['resolvers'] = { }, getFuzzyLearnset(_, args, _2, info) { return getFuzzyLearnset(args, graphqlResolveInfoToRequestedFields(info)); + }, + getNature(_, args, _2, info) { + return getNature(args, graphqlResolveInfoToRequestedFields(info)); + }, + getAllNatures(_, args, _2, info) { + return getAllNatures(args, graphqlResolveInfoToRequestedFields(info)); } } }; diff --git a/src/lib/resolvers/natureResolver.ts b/src/lib/resolvers/natureResolver.ts new file mode 100644 index 0000000000..fb0d883f84 --- /dev/null +++ b/src/lib/resolvers/natureResolver.ts @@ -0,0 +1,54 @@ +import { natures } from '#assets/natures'; +import { mapNatureDataToNatureGraphQL } from '#mappers/natureMapper'; +import type { Nature } from '#types/graphql-mapped-types'; +import type { NonNullish } from '#types/utility-types'; +import type { GraphQLSet } from '#utils/GraphQLSet'; +import { preParseInput } from '#utils/utils'; +import { validateGetNatureArgs, validateGetAllNaturesArgs, type GetAllNaturesArgs, type GetNatureArgs } from '#validations/getNatureArgs'; + +export function getNature(args: GetNatureArgs, requestedFields: GraphQLSet): Nature { + args = validateGetNatureArgs(args); + + const natureFromDataset = natures.get(preParseInput(args.nature)); + + if (!natureFromDataset) { + throw new Error(`No nature found for ${args.nature}`); + } + + const graphqlObject = mapNatureDataToNatureGraphQL({ data: natureFromDataset, requestedFields }); + + if (!graphqlObject) { + throw new Error(`Failed to get data for nature: ${args.nature}`); + } + + return graphqlObject; +} + +/** + * Returns a list of all Natures. + * + */ +export function getAllNatures(args: NonNullish, requestedFields: GraphQLSet): Nature[] { + args = validateGetAllNaturesArgs(args); + + const clonedNatures = natures.clone(); + + const natureValues = [...clonedNatures.values()].slice(args.offset, args.offset + args.take); + + const graphqlObjects: Nature[] = []; + + for (const natureData of natureValues) { + graphqlObjects.push( + mapNatureDataToNatureGraphQL({ + data: natureData, + requestedFields + }) + ); + } + + if (!graphqlObjects.length) { + throw new Error('Failed to get data for Natures'); + } + + return graphqlObjects; +} diff --git a/src/lib/types/graphql-mapped-types.ts b/src/lib/types/graphql-mapped-types.ts index bfe31fc0dd..56f8d1a74a 100644 --- a/src/lib/types/graphql-mapped-types.ts +++ b/src/lib/types/graphql-mapped-types.ts @@ -425,3 +425,17 @@ export type { TypeMatchup, TypesEnum }; + +/** A single Nature entry */ +export interface Nature { + /** The stat the nature decreases by 10% */ + decreasedStat?: Maybe; + /** The flavor of food the nature dislikes */ + dislikedFlavor?: Maybe; + /** The stat the nature increases by 10% */ + increasedStat?: Maybe; + /** The name of a nature */ + name: string; + /** The flavor of food the nature prefers */ + preferredFlavor?: Maybe; +} diff --git a/src/lib/validations/getNatureArgs.ts b/src/lib/validations/getNatureArgs.ts new file mode 100644 index 0000000000..fd391ddaf4 --- /dev/null +++ b/src/lib/validations/getNatureArgs.ts @@ -0,0 +1,56 @@ +import type { NonNullish } from '#types/utility-types'; +import { baseFuzzySchema } from '#validations/fuzzyArgs/base'; +import { s, type SchemaOf } from '@sapphire/shapeshift'; +import type { Nullish } from '@sapphire/utilities'; + +export interface GetNatureArgs { + /** + * The nature to look up + */ + nature: string; +} + +export interface GetAllNaturesArgs { + /** + * Sets the offset where to start + * @default 0 + * @minimum 0 + * @maximum 25 + */ + offset: number | Nullish; + /** + * Return only this many results, starting from the offset + * @default 26 + * @minimum 1 + * @maximum 26 + */ + take: number | Nullish; +} + +const getNatureSchema: SchemaOf = s.object({ + nature: s.string({ message: 'The nature has to be a string' }) +}); + +const getAllNaturesSchema: SchemaOf = baseFuzzySchema // + .extend({ + offset: s + .number({ message: 'The offset has to be a number' }) + .greaterThanOrEqual(0, { message: 'The offset has to be at least 0' }) + .lessThanOrEqual(25, { message: 'The offset has to be at most 25' }) + .nullish({ message: 'The offset has to be a number' }) + .transform((v) => v ?? 0), + take: s + .number({ message: 'The amount to take has to be a number' }) + .greaterThanOrEqual(1, { message: 'The amount to take has to be at least 1' }) + .lessThanOrEqual(26, { message: 'The amount to take has to be at most 26' }) + .nullish({ message: 'The amount to take has to be a number' }) + .transform((v) => v ?? 1) + }); + +export function validateGetNatureArgs(args: GetNatureArgs): GetNatureArgs { + return getNatureSchema.parse(args); +} + +export function validateGetAllNaturesArgs(args: GetAllNaturesArgs): NonNullish { + return getAllNaturesSchema.parse(args); +} diff --git a/tests/scenarios/natures/getAllNatures.test.ts b/tests/scenarios/natures/getAllNatures.test.ts new file mode 100644 index 0000000000..ed744380df --- /dev/null +++ b/tests/scenarios/natures/getAllNatures.test.ts @@ -0,0 +1,204 @@ +import { getAllNatures } from '#test-utils/queries/natures'; +import { executeGraphQL } from '#test-utils/testUtils'; + +describe('getAllNatures', () => { + test('GIVEN a limit of 5 THEN returns the first 5 Natures', async () => { + const { data } = await executeGraphQL<'getAllNatures'>({ + query: getAllNatures, + variables: { take: 5 } + }); + + expect(data.getAllNatures).toEqual([ + { + key: 'adamant', + name: 'Adamant' + }, + { + key: 'bashful', + name: 'Bashful' + }, + { + key: 'bold', + name: 'Bold' + }, + { + key: 'brave', + name: 'Brave' + }, + { + key: 'calm', + name: 'Calm' + } + ]); + + test('GIVEN a limit of 5 and offset of 5 THEN returns the second 5 Natures', async () => { + const { data } = await executeGraphQL<'getAllNatures'>({ + query: getAllNatures, + variables: { take: 5, offset: 5 } + }); + + expect(data.getAllNatures).toEqual([ + { + key: 'careful', + name: 'Careful' + }, + { + key: 'docile', + name: 'Docile' + }, + { + key: 'gentle', + name: 'Gentle' + }, + { + key: 'hardy', + name: 'Hardy' + }, + { + key: 'hasty', + name: 'Hasty' + } + ]); + }); + + test('GIVEN a limit of 5 and reverse THEN returns the last 5 Natures', async () => { + const { data } = await executeGraphQL<'getAllNatures'>({ + query: getAllNatures, + variables: { take: 5, reverse: true } + }); + + expect(data.getAllNatures).toEqual([ + { + key: 'adamant', + name: 'Adamant' + }, + { + key: 'bashful', + name: 'Bashful' + }, + { + key: 'bold', + name: 'Bold' + }, + { + key: 'brave', + name: 'Brave' + }, + { + key: 'calm', + name: 'Calm' + } + ]); + }); + + test('GIVEN no parameters THEN returns all Natures', async () => { + const { data } = await executeGraphQL<'getAllNatures'>({ + query: getAllNatures, + variables: {} + }); + + expect(data.getAllNatures).toEqual([ + { + key: 'adamant', + name: 'Adamant' + }, + { + key: 'bashful', + name: 'Bashful' + }, + { + key: 'bold', + name: 'Bold' + }, + { + key: 'brave', + name: 'Brave' + }, + { + key: 'calm', + name: 'Calm' + }, + { + key: 'careful', + name: 'Careful' + }, + { + key: 'docile', + name: 'Docile' + }, + { + key: 'gentle', + name: 'Gentle' + }, + { + key: 'hardy', + name: 'Hardy' + }, + { + key: 'hasty', + name: 'Hasty' + }, + { + key: 'impish', + name: 'Impish' + }, + { + key: 'jolly', + name: 'Jolly' + }, + { + key: 'lax', + name: 'Lax' + }, + { + key: 'lonely', + name: 'Lonely' + }, + { + key: 'mild', + name: 'Mild' + }, + { + key: 'modest', + name: 'Modest' + }, + { + key: 'naive', + name: 'Naive' + }, + { + key: 'naughty', + name: 'Naughty' + }, + { + key: 'quiet', + name: 'Quiet' + }, + { + key: 'quirky', + name: 'Quirky' + }, + { + key: 'rash', + name: 'Rash' + }, + { + key: 'relaxed', + name: 'Relaxed' + }, + { + key: 'sassy', + name: 'Sassy' + }, + { + key: 'serious', + name: 'Serious' + }, + { + key: 'timid', + name: 'Timid' + } + ]); + }); + }); +}); diff --git a/tests/scenarios/natures/getNature.test.ts b/tests/scenarios/natures/getNature.test.ts new file mode 100644 index 0000000000..526ec20b09 --- /dev/null +++ b/tests/scenarios/natures/getNature.test.ts @@ -0,0 +1,46 @@ +import { getNatureName, getNatureWithFullData } from '#test-utils/queries/natures'; +import { executeGraphQL } from '#test-utils/testUtils'; + +describe('getNature', () => { + describe('Regular Nature name only requests', () => { + test('GIVEN a valid name THEN returns Nature', async () => { + const { data } = await executeGraphQL<'getNature'>({ + query: getNatureName, + variables: { nature: 'adamant' } + }); + + expect(data.getNature.name).toEqual('Adamant'); + }); + }); + + describe('Regular Nature full data requests', () => { + test('GIVEN valid nature request THEN returns Nature WITH all data', async () => { + const { data } = await executeGraphQL<'getNature'>({ + query: getNatureWithFullData, + variables: { nature: 'adamant' } + }); + + expect(data.getNature).toEqual({ + name: 'Adamant', + increasedStat: 'Attack', + decreasedStat: 'Special Attack', + preferredFlavor: 'Spicy', + dislikedFlavor: 'Dry' + }); + }); + }); + + describe('Error Requests', () => { + test('GIVEN an invalid nature THEN returns error', async () => { + const data = await executeGraphQL({ + query: getNatureName, + variables: { nature: 'totally_invalid_nature' } + }); + + expect(data.errors).toHaveLength(1); + expect(data.errors?.[0].message).toBe( + 'Variable "$nature" got invalid value "totally_invalid_nature"; Value "totally_invalid_nature" does not exist in "NaturesEnum" enum.' + ); + }); + }); +}); diff --git a/tests/testUtils/queries/natures.ts b/tests/testUtils/queries/natures.ts new file mode 100644 index 0000000000..dce4153fb9 --- /dev/null +++ b/tests/testUtils/queries/natures.ts @@ -0,0 +1,30 @@ +import gql from 'graphql-tag'; + +export const getNatureName = gql` + query ($nature: NaturesEnum!) { + getNature(nature: $nature) { + name + } + } +`; + +export const getNatureWithFullData = gql` + query ($nature: NaturesEnum!) { + getNature(nature: $nature) { + name + increasedStat + decreasedStat + preferredFlavor + dislikedFlavor + } + } +`; + +export const getAllNatures = gql` + query ($offset: Int, $take: Int) { + getAllNatures(offset: $offset, take: $take) { + key + name + } + } +`; diff --git a/tests/testUtils/types.d.ts b/tests/testUtils/types.d.ts index dee3090cfb..91e1253273 100644 --- a/tests/testUtils/types.d.ts +++ b/tests/testUtils/types.d.ts @@ -1,4 +1,4 @@ -import { Ability, Item, Learnset, Move, Pokemon, TypeMatchup } from '#types/graphql-mapped-types'; +import { Ability, Item, Learnset, Move, Pokemon, TypeMatchup, Nature } from '#types/graphql-mapped-types'; export interface Query { /** Gets the details on a Pokémon ability, using the ability name */ @@ -93,4 +93,14 @@ export interface Query { getPokemonByDexNumber: Pokemon; /** Gets the type matchup data for the given type or types */ getTypeMatchup: TypeMatchup; + /** Gets the details on a Pokémon ability, using the ability name */ + getNature: Nature; + /** + * Returns a list of all the Natures in Pokémon. + * + * For every Nature all the data on each requested field is returned. + * + * You can provide `take` to limit the amount of Pokémon to return (default: 1), set the offset of where to start with `offset`, and reverse the entire array with `reverse`. + */ + getAllNatures: Array; }