Skip to main content Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-graphql --skill graphql-resolversLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Métiers associés SOC
Basé sur la classification professionnelle SOC
Explorateur de fichiers
6 fichiers name graphql-resolvers description Write efficient resolvers with DataLoader, batching, and N+1 prevention sasmp_version 1.3.0 bonded_agent 03-graphql-resolvers bond_type PRIMARY_BOND version 2.0.0 complexity intermediate estimated_time 4-6 hours prerequisites ["graphql-fundamentals","graphql-schema-design"]
GraphQL Resolvers Skill
Build performant data fetching with proper patterns
Overview
Master resolver implementation including the critical DataLoader pattern for preventing N+1 queries, context design, and error handling strategies.
Quick Reference
Pattern Purpose When to Use DataLoader Batch + cache Any relationship field Context Request-scoped data Auth, loaders, datasources Field resolver Computed fields Derived data Root resolver Entry points Query/Mutation fields
Core Patterns
1. Resolver Signature
const resolvers = {
Query : {
user : async (_, { id }, { dataSources }) => {
return dataSources.users .findById (id);
},
},
User : {
posts : async (user, { first = 10 }, { loaders }) => {
return loaders.postsByAuthor .load (user.id );
},
fullName : (user ) => `${user.firstName} ${user.lastName} ` ,
},
};
2. DataLoader Pattern
const DataLoader = require ('dataloader' );
const createLoaders = ( ) => ({
postsByAuthor : new DataLoader (async (authorIds) => {
const posts = await db.posts .findAll ({
where : { authorId : { [Op .in ]: authorIds } }
});
const postsByAuthor = {};
posts.forEach (post => {
if (!postsByAuthor[post.authorId ]) {
postsByAuthor[post.authorId ] = [];
}
postsByAuthor[post.authorId ].push (post);
});
return authorIds.map (id => postsByAuthor[id] || []);
}),
userById : new DataLoader (async (ids) => {
const users = await db.users .findAll ({
where : { id : { [Op .in ]: ids } }
});
const userMap = new Map (users.map (u => [u.id , u]));
return ids.map (id => userMap.get (id) || null );
}),
});
const resolvers = {
Post : {
author : (post, _, { loaders } ) => {
return loaders.userById .load (post.authorId );
},
},
User : {
posts : (user, _, { loaders } ) => {
return loaders.postsByAuthor .load (user.id );
},
},
};
3. Context Setup const createContext = async ({ req, res } ) => {
const token = req.headers .authorization ?.replace ('Bearer ' , '' );
const user = token ? await verifyToken (token) : null ;
const loaders = createLoaders ();
const dataSources = {
users : new UserDataSource (db),
posts : new PostDataSource (db),
};
const requestId = req.headers ['x-request-id' ] || crypto.randomUUID ();
return {
user,
loaders,
dataSources,
requestId,
};
};
const server = new ApolloServer ({
typeDefs,
resolvers,
context : createContext,
});
4. Error Handling import { GraphQLError } from 'graphql' ;
const resolvers = {
Mutation : {
createUser : async (_, { input }, { dataSources, user }) => {
if (!user) {
throw new GraphQLError ('Not authenticated' , {
extensions : { code : 'UNAUTHENTICATED' }
});
}
const validationErrors = validateInput (input);
if (validationErrors.length > 0 ) {
return { user : null , errors : validationErrors };
}
try {
const newUser = await dataSources.users .create (input);
return { user : newUser, errors : [] };
} catch (error) {
if (error.code === 'DUPLICATE_EMAIL' ) {
return {
user : null ,
errors : [{ field : 'email' , message : 'Already exists' }]
};
}
throw new GraphQLError ('Internal error' , {
extensions : { code : 'INTERNAL_ERROR' }
});
}
},
},
};
5. Subscription Resolvers import { PubSub , withFilter } from 'graphql-subscriptions' ;
const pubsub = new PubSub ();
const resolvers = {
Mutation : {
sendMessage : async (_, { input }, { dataSources }) => {
const message = await dataSources.messages .create (input);
pubsub.publish ('MESSAGE_SENT' , {
messageSent : message,
channelId : input.channelId ,
});
return message;
},
},
Subscription : {
userCreated : {
subscribe : () => pubsub.asyncIterator (['USER_CREATED' ]),
},
messageSent : {
subscribe : withFilter (
() => pubsub.asyncIterator (['MESSAGE_SENT' ]),
(payload, variables ) => {
return payload.channelId === variables.channelId ;
}
),
},
},
};
Performance Targets Resolver Type Target Action if Exceeded Simple field < 10ms Check DB indexes DataLoader batch < 50ms Optimize query Complex computation < 200ms Consider caching Total request < 500ms Profile and optimize
Troubleshooting Issue Symptom Solution N+1 queries Slow, many DB calls Use DataLoader Memory leak Growing memory Create loaders per request Stale data Wrong results Clear DataLoader cache Race condition Intermittent errors Don't mutate context
Debug Techniques
const loader = new DataLoader (async (keys) => {
console .log (`Batching ${keys.length} keys` );
});
const withTiming = (resolver ) => async (...args) => {
const start = Date .now ();
const result = await resolver (...args);
console .log (`Took ${Date .now() - start} ms` );
return result;
};
const loggingPlugin = {
requestDidStart ( ) {
const start = Date .now ();
return {
willSendResponse ( ) {
console .log (`Request took ${Date .now() - start} ms` );
},
};
},
};
Usage Skill("graphql-resolvers")
Related Skills
graphql-schema-design - Schema that resolvers implement
graphql-apollo-server - Server configuration
graphql-security - Auth in resolvers
Related Agent
03-graphql-resolvers - For detailed guidance