UNPKG

4.59 kBJavaScriptView Raw
1import { concatAST, Kind, visit } from 'graphql';
2import { ClientSideBaseVisitor, DocumentMode } from '@graphql-codegen/visitor-plugin-common';
3import autoBind from 'auto-bind';
4import { pascalCase } from 'pascal-case';
5import { extname } from 'path';
6
7class ReactApolloVisitor extends ClientSideBaseVisitor {
8 constructor(schema, fragments, rawConfig, documents) {
9 super(schema, fragments, rawConfig, {});
10 this.imports = new Set();
11 this._externalImportPrefix = this.config.importOperationTypesFrom ? `${this.config.importOperationTypesFrom}.` : '';
12 this._documents = documents;
13 autoBind(this);
14 }
15 getOffixReactHooksImport() {
16 return `import * as OffixReactHooks from "react-offix-hooks";`;
17 }
18 getDocumentNodeVariable(node, documentVariableName) {
19 return this.config.documentMode === DocumentMode.external ? `Operations.${node.name.value}` : documentVariableName;
20 }
21 getImports() {
22 const baseImports = super.getImports({ excludeFragments: true });
23 const hasOperations = this._collectedOperations.length > 0;
24 if (!hasOperations) {
25 return baseImports;
26 }
27 return [...baseImports, ...Array.from(this.imports)];
28 }
29 _buildHooks(node, operationType, documentVariableName, operationResultType, operationVariablesTypes) {
30 const operationName = this.convertName(node.name.value, {
31 useTypesPrefix: false,
32 });
33 this.imports.add(this.getOffixReactHooksImport());
34 const hookFns = [];
35 if (operationType === 'Mutation') {
36 hookFns.push(`export function useOffline${operationName}(baseOptions?: OffixReactHooks.${operationType}HookOptions<${operationResultType}, ${operationVariablesTypes}>) {
37 return OffixReactHooks.useOfflineMutation<${operationResultType}, ${operationVariablesTypes}>(${this.getDocumentNodeVariable(node, documentVariableName)}, baseOptions);
38}`);
39 }
40 return [...hookFns].join('\n');
41 }
42 buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) {
43 operationResultType = this._externalImportPrefix + operationResultType;
44 operationVariablesTypes = this._externalImportPrefix + operationVariablesTypes;
45 const hooks = this._buildHooks(node, operationType, documentVariableName, operationResultType, operationVariablesTypes);
46 return [hooks].filter(a => a).join('\n');
47 }
48 OperationDefinition(node) {
49 if (!node.name || !node.name.value) {
50 return null;
51 }
52 this._collectedOperations.push(node);
53 const documentVariableName = this.convertName(node, {
54 suffix: this.config.documentVariableSuffix,
55 prefix: this.config.documentVariablePrefix,
56 useTypesPrefix: false,
57 });
58 const operationType = pascalCase(node.operation);
59 const operationTypeSuffix = this.getOperationSuffix(node, operationType);
60 const operationResultType = this.convertName(node, {
61 suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix,
62 });
63 const operationVariablesTypes = this.convertName(node, {
64 suffix: operationTypeSuffix + 'Variables',
65 });
66 const additional = this.buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes);
67 return [additional].filter(a => a).join('\n');
68 }
69}
70
71const plugin = (schema, documents, config) => {
72 const allAst = concatAST(documents.map(v => v.document));
73 const allFragments = [
74 ...allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION).map(fragmentDef => ({
75 node: fragmentDef,
76 name: fragmentDef.name.value,
77 onType: fragmentDef.typeCondition.name.value,
78 isExternal: false,
79 })),
80 ...(config.externalFragments || []),
81 ];
82 const visitor = new ReactApolloVisitor(schema, allFragments, config, documents);
83 const visitorResult = visit(allAst, { leave: visitor });
84 return {
85 prepend: visitor.getImports(),
86 content: [...visitorResult.definitions.filter(t => typeof t === 'string')].join('\n'),
87 };
88};
89const validate = async (_schema, _documents, _config, outputFile) => {
90 if (extname(outputFile) !== '.tsx' && extname(outputFile) !== '.ts') {
91 throw new Error(`Plugin "react-apollo" requires extension to be ".tsx" or ".ts!`);
92 }
93};
94
95export { ReactApolloVisitor, plugin, validate };
96//# sourceMappingURL=index.esm.js.map