GraphQL Code Generator plugin for generating TypeScript-typed React Apollo components, hooks, and HOCs from GraphQL operations
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The ReactApolloVisitor class is the core engine that generates React Apollo-specific TypeScript code. It extends the base ClientSideBaseVisitor and provides specialized methods for creating React hooks, components, HOCs, and type definitions from GraphQL operations.
class ReactApolloVisitor extends ClientSideBaseVisitor<ReactApolloRawPluginConfig, ReactApolloPluginConfig> {
constructor(
schema: GraphQLSchema,
fragments: LoadedFragment[],
rawConfig: ReactApolloRawPluginConfig,
documents: Types.DocumentFile[],
);
getImports(): string[];
buildOperation(
node: OperationDefinitionNode,
documentVariableName: string,
operationType: string,
operationResultType: string,
operationVariablesTypes: string,
hasRequiredVariables: boolean,
): string;
get fragments(): string;
}Creates a new visitor instance with processed configuration and schema information.
GraphQLSchema - The GraphQL schema to generate code fromLoadedFragment[] - Array of GraphQL fragments available for operationsReactApolloRawPluginConfig - Raw plugin configurationTypes.DocumentFile[] - GraphQL document files containing operationsThe constructor processes raw configuration into typed configuration with defaults:
// Example of internal configuration processing
{
withHooks: getConfigValue(rawConfig.withHooks, true),
withComponent: getConfigValue(rawConfig.withComponent, false),
withHOC: getConfigValue(rawConfig.withHOC, false),
reactApolloVersion: getConfigValue(rawConfig.reactApolloVersion, 3),
componentSuffix: getConfigValue(rawConfig.componentSuffix, 'Component'),
// ... other options with defaults
}Returns an array of import statements required for the generated code.
getImports(): string[];Returns: Array of import statements based on configuration and generated code needs.
For Apollo Client v3 with hooks:
[
"import * as React from 'react';",
"import * as Apollo from '@apollo/client';",
"const defaultOptions = {} as const;"
]For Apollo Client v2 with components and HOCs:
[
"import * as React from 'react';",
"import * as ApolloReactCommon from '@apollo/react-common';",
"import * as ApolloReactComponents from '@apollo/react-components';",
"import * as ApolloReactHoc from '@apollo/react-hoc';",
"import * as ApolloReactHooks from '@apollo/react-hooks';"
]Generates React Apollo code for a specific GraphQL operation based on configuration.
buildOperation(
node: OperationDefinitionNode,
documentVariableName: string,
operationType: string,
operationResultType: string,
operationVariablesTypes: string,
hasRequiredVariables: boolean,
): string;OperationDefinitionNode - GraphQL operation AST nodestring - Name of the document variablestring - Type of operation ("Query", "Mutation", "Subscription")string - TypeScript type for operation resultstring - TypeScript type for operation variablesboolean - Whether operation has required variablesThe method generates different code patterns based on configuration:
// Query hooks
export function useGetUserQuery(baseOptions?: Apollo.QueryHookOptions<GetUserQuery, GetUserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetUserQuery, GetUserQueryVariables>(GetUserDocument, options);
}
// Lazy query hooks
export function useGetUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetUserQuery, GetUserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetUserQuery, GetUserQueryVariables>(GetUserDocument, options);
}
// Suspense query hooks (Apollo Client 3.7+)
export function useGetUserSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<GetUserQuery, GetUserQueryVariables>) {
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<GetUserQuery, GetUserQueryVariables>(GetUserDocument, options);
}
// Hook result types
export type GetUserQueryHookResult = ReturnType<typeof useGetUserQuery>;
export type GetUserLazyQueryHookResult = ReturnType<typeof useGetUserLazyQuery>;// Component props type
export type GetUserComponentProps = Omit<ApolloReactComponents.QueryComponentOptions<GetUserQuery, GetUserQueryVariables>, 'query'>;
// Component
export const GetUserComponent = (props: GetUserComponentProps) => (
<ApolloReactComponents.Query<GetUserQuery, GetUserQueryVariables> query={GetUserDocument} {...props} />
);// Props type for HOC
export type GetUserProps<TChildProps = {}, TDataName extends string = 'data'> = {
[key in TDataName]: ApolloReactHoc.DataValue<GetUserQuery, GetUserQueryVariables>
} & TChildProps;
// HOC function
export function withGetUser<TProps, TChildProps = {}, TDataName extends string = 'data'>(
operationOptions?: ApolloReactHoc.OperationOption<TProps, GetUserQuery, GetUserQueryVariables, GetUserProps<TChildProps, TDataName>>
) {
return ApolloReactHoc.withQuery<TProps, GetUserQuery, GetUserQueryVariables, GetUserProps<TChildProps, TDataName>>(
GetUserDocument,
{ alias: 'getUserQuery', ...operationOptions }
);
}// Mutation function type (withMutationFn: true)
export type CreateUserMutationFn = Apollo.MutationFunction<CreateUserMutation, CreateUserMutationVariables>;
// Result types (withResultType: true)
export type GetUserQueryResult = Apollo.QueryResult<GetUserQuery, GetUserQueryVariables>;
export type CreateUserMutationResult = Apollo.MutationResult<CreateUserMutation>;
// Mutation options type (withMutationOptionsType: true)
export type CreateUserMutationOptions = Apollo.BaseMutationOptions<CreateUserMutation, CreateUserMutationVariables>;
// Refetch function (withRefetchFn: true)
export function refetchGetUserQuery(variables?: GetUserQueryVariables) {
return { query: GetUserDocument, variables: variables }
}Returns generated fragment-related code, including fragment hooks when enabled.
get fragments(): string;When fragment hooks are enabled, generates useFragment wrappers:
// Generated fragment hook
export function useUserFieldsFragment<F = { id: string }>(identifiers: F) {
return Apollo.useFragment<UserFieldsFragment>({
fragment: UserFieldsFragmentDoc,
fragmentName: "UserFields",
from: {
__typename: "User",
...identifiers,
},
});
}
// Fragment hook result type
export type UserFieldsFragmentHookResult = ReturnType<typeof useUserFieldsFragment>;The visitor is typically used internally by the plugin function:
// Internal plugin usage
const visitor = new ReactApolloVisitor(schema, allFragments, config, documents);
const visitorResult = oldVisit(allAst, { leave: visitor });
const output = {
prepend: visitor.getImports(),
content: [
visitor.fragments,
...visitorResult.definitions.filter(t => typeof t === 'string'),
].join('\n'),
};The visitor respects all configuration options:
The visitor ensures complete type safety by: