UNPKG

6.36 kBJavaScriptView Raw
1import { isEnumType, isNonNullType, concatAST, Kind, visit } from 'graphql';
2import { BaseSelectionSetProcessor, indent, BaseDocumentsVisitor, getConfigValue, wrapTypeWithModifiers, PreResolveTypesProcessor, SelectionSetToObject, optimizeOperations } from '@graphql-codegen/visitor-plugin-common';
3import { FlowOperationVariablesToObject } from '@graphql-codegen/flow';
4import autoBind from 'auto-bind';
5
6class FlowWithPickSelectionSetProcessor extends BaseSelectionSetProcessor {
7 transformAliasesPrimitiveFields(schemaType, fields) {
8 if (fields.length === 0) {
9 return [];
10 }
11 const useFlowExactObject = this.config.useFlowExactObjects;
12 const useFlowReadOnlyTypes = this.config.useFlowReadOnlyTypes;
13 const parentName = (this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
14 this.config.convertName(schemaType.name, {
15 useTypesPrefix: true,
16 });
17 return [
18 `{${useFlowExactObject ? '|' : ''} ${fields
19 .map(aliasedField => `${useFlowReadOnlyTypes ? '+' : ''}${aliasedField.alias}: $ElementType<${parentName}, '${aliasedField.fieldName}'>`)
20 .join(', ')} ${useFlowExactObject ? '|' : ''}}`,
21 ];
22 }
23 buildFieldsIntoObject(allObjectsMerged) {
24 return `...{ ${allObjectsMerged.join(', ')} }`;
25 }
26 buildSelectionSetFromStrings(pieces) {
27 if (pieces.length === 0) {
28 return null;
29 }
30 else if (pieces.length === 1) {
31 return pieces[0];
32 }
33 else {
34 return `({\n ${pieces.map(t => indent(`...${t}`)).join(`,\n`)}\n})`;
35 }
36 }
37 transformLinkFields(fields) {
38 if (fields.length === 0) {
39 return [];
40 }
41 const useFlowExactObject = this.config.useFlowExactObjects;
42 const useFlowReadOnlyTypes = this.config.useFlowReadOnlyTypes;
43 return [
44 `{${useFlowExactObject ? '|' : ''} ${fields
45 .map(field => `${useFlowReadOnlyTypes ? '+' : ''}${field.alias || field.name}: ${field.selectionSet}`)
46 .join(', ')} ${useFlowExactObject ? '|' : ''}}`,
47 ];
48 }
49 transformPrimitiveFields(schemaType, fields) {
50 if (fields.length === 0) {
51 return [];
52 }
53 const useFlowExactObject = this.config.useFlowExactObjects;
54 const useFlowReadOnlyTypes = this.config.useFlowReadOnlyTypes;
55 const formatNamedField = this.config.formatNamedField;
56 const parentName = (this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
57 this.config.convertName(schemaType.name, {
58 useTypesPrefix: true,
59 });
60 const fieldObj = schemaType.getFields();
61 return [
62 `$Pick<${parentName}, {${useFlowExactObject ? '|' : ''} ${fields
63 .map(fieldName => `${useFlowReadOnlyTypes ? '+' : ''}${formatNamedField(fieldName, fieldObj[fieldName].type)}: *`)
64 .join(', ')} ${useFlowExactObject ? '|' : ''}}>`,
65 ];
66 }
67 transformTypenameField(type, name) {
68 return [`{ ${name}: ${type} }`];
69 }
70}
71
72class FlowDocumentsVisitor extends BaseDocumentsVisitor {
73 constructor(schema, config, allFragments) {
74 super(config, {
75 useFlowExactObjects: getConfigValue(config.useFlowExactObjects, true),
76 useFlowReadOnlyTypes: getConfigValue(config.useFlowReadOnlyTypes, false),
77 }, schema);
78 autoBind(this);
79 const wrapArray = (type) => `Array<${type}>`;
80 const wrapOptional = (type) => `?${type}`;
81 const formatNamedField = (name, type) => {
82 const optional = !!type && !isNonNullType(type);
83 return `${name}${optional ? '?' : ''}`;
84 };
85 const processorConfig = {
86 namespacedImportName: this.config.namespacedImportName,
87 convertName: this.convertName.bind(this),
88 enumPrefix: this.config.enumPrefix,
89 scalars: this.scalars,
90 formatNamedField,
91 wrapTypeWithModifiers(baseType, type) {
92 return wrapTypeWithModifiers(baseType, type, { wrapOptional, wrapArray });
93 },
94 };
95 const processor = config.preResolveTypes
96 ? new PreResolveTypesProcessor(processorConfig)
97 : new FlowWithPickSelectionSetProcessor({
98 ...processorConfig,
99 useFlowExactObjects: this.config.useFlowExactObjects,
100 useFlowReadOnlyTypes: this.config.useFlowReadOnlyTypes,
101 });
102 const enumsNames = Object.keys(schema.getTypeMap()).filter(typeName => isEnumType(schema.getType(typeName)));
103 this.setSelectionSetHandler(new SelectionSetToObject(processor, this.scalars, this.schema, this.convertName.bind(this), this.getFragmentSuffix.bind(this), allFragments, this.config));
104 this.setVariablesTransformer(new FlowOperationVariablesToObject(this.scalars, this.convertName.bind(this), this.config.namespacedImportName, enumsNames, this.config.enumPrefix));
105 }
106 getPunctuation(declarationKind) {
107 return declarationKind === 'type' ? ',' : ';';
108 }
109}
110
111const plugin = (schema, rawDocuments, config) => {
112 const documents = config.flattenGeneratedTypes
113 ? optimizeOperations(schema, rawDocuments, { includeFragments: true })
114 : rawDocuments;
115 const prefix = config.preResolveTypes
116 ? ''
117 : `type $Pick<Origin: Object, Keys: Object> = $ObjMapi<Keys, <Key>(k: Key) => $ElementType<Origin, Key>>;\n`;
118 const allAst = concatAST(documents.map(v => v.document));
119 const includedFragments = allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION);
120 const allFragments = [
121 ...includedFragments.map(fragmentDef => ({
122 node: fragmentDef,
123 name: fragmentDef.name.value,
124 onType: fragmentDef.typeCondition.name.value,
125 isExternal: false,
126 })),
127 ...(config.externalFragments || []),
128 ];
129 const visitorResult = visit(allAst, {
130 leave: new FlowDocumentsVisitor(schema, config, allFragments),
131 });
132 return {
133 prepend: ['// @flow \n'],
134 content: [prefix, ...visitorResult.definitions].join('\n'),
135 };
136};
137
138export { plugin };
139//# sourceMappingURL=index.esm.js.map