UNPKG

@graphql-codegen/typescript-msw

Version:

GraphQL Code Generator plugin for generating MSW mock handlers based on GraphQL operations

72 lines (71 loc) 3.33 kB
import autoBind from 'auto-bind'; import { pascalCase } from 'change-case-all'; import { print } from 'graphql'; import { ClientSideBaseVisitor, getConfigValue, } from '@graphql-codegen/visitor-plugin-common'; export class MSWVisitor extends ClientSideBaseVisitor { constructor(schema, fragments, rawConfig) { super(schema, fragments, rawConfig, { link: getConfigValue(rawConfig.link, undefined) }); this._operationsToInclude = []; autoBind(this); this._externalImportPrefix = this.config.importOperationTypesFrom ? `${this.config.importOperationTypesFrom}.` : ''; } getImports() { const hasOperations = this._collectedOperations.length > 0; if (!hasOperations) { return []; } return [`import { graphql, ResponseResolver, GraphQLRequest, GraphQLContext } from 'msw'`]; } getContent() { const { link } = this.config; let endpoint; if (link) { endpoint = `const ${link.name} = graphql.link('${link.endpoint}')\n`; } const suffix = pascalCase((link === null || link === void 0 ? void 0 : link.name) || ''); const operations = this._operationsToInclude.map(({ node, operationType, operationResultType, operationVariablesTypes }) => { if (operationType === 'Query' || operationType === 'Mutation') { const handlerName = `mock${pascalCase(node.name.value)}${operationType}${suffix}`; /** @ts-expect-error name DOES exist on @type{import('graphql').SelectionNode} */ const selections = node.selectionSet.selections.map(sel => sel.name.value).join(', '); const variables = node.variableDefinitions.map(def => def.variable.name.value).join(', '); return `/** * @param resolver a function that accepts a captured request and may return a mocked response. * @see https://mswjs.io/docs/basics/response-resolver * @example * ${handlerName}((req, res, ctx) => {${variables && `\n * const { ${variables} } = req.variables;`} * return res( * ctx.data({ ${selections} }) * ) * }) */ export const ${handlerName} = (resolver: ResponseResolver<GraphQLRequest<${operationVariablesTypes}>, GraphQLContext<${operationResultType}>, any>) => ${(link === null || link === void 0 ? void 0 : link.name) || 'graphql'}.${operationType.toLowerCase()}<${operationResultType}, ${operationVariablesTypes}>( '${node.name.value}', resolver )\n`; } return ''; }); return [endpoint, ...operations].join('\n'); } buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) { operationResultType = this._externalImportPrefix + operationResultType; operationVariablesTypes = this._externalImportPrefix + operationVariablesTypes; if (node.name == null) { throw new Error("Plugin 'msw' cannot generate mocks for unnamed operation.\n\n" + print(node)); } else { this._operationsToInclude.push({ node, documentVariableName, operationType, operationResultType, operationVariablesTypes, }); } return null; } }