@graphql-codegen/flow-operations
Version:
GraphQL Code Generator plugin for generating Flow types for GraphQL operations (query/mutation/subscription/fragment)
60 lines (59 loc) • 3.42 kB
JavaScript
import autoBind from 'auto-bind';
import { isEnumType, isNonNullType, } from 'graphql';
import { FlowOperationVariablesToObject } from '@graphql-codegen/flow';
import { BaseDocumentsVisitor, generateFragmentImportStatement, getConfigValue, PreResolveTypesProcessor, SelectionSetToObject, wrapTypeWithModifiers, } from '@graphql-codegen/visitor-plugin-common';
import { FlowWithPickSelectionSetProcessor } from './flow-selection-set-processor.js';
class FlowSelectionSetToObject extends SelectionSetToObject {
getUnknownType() {
return 'any';
}
createNext(parentSchemaType, selectionSet) {
return new FlowSelectionSetToObject(this._processor, this._scalars, this._schema, this._convertName.bind(this), this._getFragmentSuffix.bind(this), this._loadedFragments, this._config, parentSchemaType, selectionSet);
}
}
export class FlowDocumentsVisitor extends BaseDocumentsVisitor {
constructor(schema, config, allFragments) {
super(config, {
useFlowExactObjects: getConfigValue(config.useFlowExactObjects, true),
useFlowReadOnlyTypes: getConfigValue(config.useFlowReadOnlyTypes, false),
}, schema);
autoBind(this);
const wrapArray = (type) => `${this.config.useFlowReadOnlyTypes ? '$ReadOnlyArray' : 'Array'}<${type}>`;
const wrapOptional = (type) => `?${type}`;
const { useFlowReadOnlyTypes } = this.config;
const formatNamedField = (name, type, isConditional = false) => {
const optional = (!!type && !isNonNullType(type)) || isConditional;
return `${useFlowReadOnlyTypes ? '+' : ''}${name}${optional ? '?' : ''}`;
};
const processorConfig = {
namespacedImportName: this.config.namespacedImportName,
convertName: this.convertName.bind(this),
enumPrefix: this.config.enumPrefix,
scalars: this.scalars,
formatNamedField,
wrapTypeWithModifiers(baseType, type) {
return wrapTypeWithModifiers(baseType, type, { wrapOptional, wrapArray });
},
};
const processor = config.preResolveTypes
? new PreResolveTypesProcessor(processorConfig)
: new FlowWithPickSelectionSetProcessor({
...processorConfig,
useFlowExactObjects: this.config.useFlowExactObjects,
});
const enumsNames = Object.keys(schema.getTypeMap()).filter(typeName => isEnumType(schema.getType(typeName)));
this.setSelectionSetHandler(new FlowSelectionSetToObject(processor, this.scalars, this.schema, this.convertName.bind(this), this.getFragmentSuffix.bind(this), allFragments, this.config));
this.setVariablesTransformer(new FlowOperationVariablesToObject(this.scalars, this.convertName.bind(this), this.config.namespacedImportName, enumsNames, this.config.enumPrefix, {}, true));
}
getPunctuation(declarationKind) {
return declarationKind === 'type' ? ',' : ';';
}
getImports() {
return !this.config.globalNamespace && !this.config.inlineFragmentTypes
? this.config.fragmentImports
// In flow, all non ` * as x` imports must be type imports
.map(fragmentImport => ({ ...fragmentImport, typesImport: true }))
.map(fragmentImport => generateFragmentImportStatement(fragmentImport, 'type'))
: [];
}
}