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