UNPKG

15.7 kBTypeScriptView Raw
1import { ParsedConfig, RawConfig, BaseVisitor, BaseVisitorConvertOptions } from './base-visitor';
2import { NormalizedScalarsMap, EnumValuesMap, ParsedEnumValuesMap, DeclarationKind, ConvertOptions, AvoidOptionalsConfig } from './types';
3import { DeclarationBlockConfig } from './utils';
4import { NameNode, ListTypeNode, NamedTypeNode, FieldDefinitionNode, ObjectTypeDefinitionNode, GraphQLSchema, NonNullTypeNode, UnionTypeDefinitionNode, ScalarTypeDefinitionNode, InterfaceTypeDefinitionNode, GraphQLNamedType, DirectiveDefinitionNode, InputValueDefinitionNode, EnumTypeDefinitionNode, ASTNode } from 'graphql';
5import { OperationVariablesToObject } from './variables-to-object';
6import { ParsedMapper } from './mappers';
7import { ApolloFederation } from '@graphql-codegen/plugin-helpers';
8export interface ParsedResolversConfig extends ParsedConfig {
9 contextType: ParsedMapper;
10 fieldContextTypes: Array<string>;
11 directiveContextTypes: Array<string>;
12 rootValueType: ParsedMapper;
13 mappers: {
14 [typeName: string]: ParsedMapper;
15 };
16 defaultMapper: ParsedMapper | null;
17 avoidOptionals: AvoidOptionalsConfig;
18 addUnderscoreToArgsType: boolean;
19 enumValues: ParsedEnumValuesMap;
20 resolverTypeWrapperSignature: string;
21 federation: boolean;
22 enumPrefix: boolean;
23 optionalResolveType: boolean;
24 immutableTypes: boolean;
25 namespacedImportName: string;
26 resolverTypeSuffix: string;
27 allResolversTypeName: string;
28 internalResolversPrefix: string;
29 onlyResolveTypeForInterfaces: boolean;
30 directiveResolverMappings: Record<string, string>;
31}
32export interface RawResolversConfig extends RawConfig {
33 /**
34 * @description Adds `_` to generated `Args` types in order to avoid duplicate identifiers.
35 *
36 * @exampleMarkdown
37 * ```yaml
38 * config:
39 * addUnderscoreToArgsType: true
40 * ```
41 *
42 */
43 addUnderscoreToArgsType?: boolean;
44 /**
45 * @description Use this configuration to set a custom type for your `context`, and it will
46 * affect all the resolvers, without the need to override it using generics each time.
47 * If you wish to use an external type and import it from another file, you can use `add` plugin
48 * and add the required `import` statement, or you can use a `module#type` syntax.
49 *
50 * @exampleMarkdown
51 * ## Custom Context Type
52 *
53 * ```yaml
54 * plugins
55 * config:
56 * contextType: MyContext
57 * ```
58 *
59 * ## Custom Context Type
60 *
61 * ```yaml
62 * plugins
63 * config:
64 * contextType: ./my-types#MyContext
65 * ```
66 */
67 contextType?: string;
68 /**
69 * @description Use this to set a custom type for a specific field `context`.
70 * It will only affect the targeted resolvers.
71 * You can either use `Field.Path#ContextTypeName` or `Field.Path#ExternalFileName#ContextTypeName`
72 *
73 * @exampleMarkdown
74 * ## Custom Field Context Types
75 *
76 * ```yaml
77 * plugins
78 * config:
79 * fieldContextTypes:
80 * - MyType.foo#CustomContextType
81 * - MyType.bar#./my-file#ContextTypeOne
82 * ```
83 *
84 */
85 fieldContextTypes?: Array<string>;
86 /**
87 * @description Use this configuration to set a custom type for the `rootValue`, and it will
88 * affect resolvers of all root types (Query, Mutation and Subscription), without the need to override it using generics each time.
89 * If you wish to use an external type and import it from another file, you can use `add` plugin
90 * and add the required `import` statement, or you can use both `module#type` or `module#namespace#type` syntax.
91 *
92 * @exampleMarkdown
93 * ## Custom RootValue Type
94 *
95 * ```yaml
96 * plugins
97 * config:
98 * rootValueType: MyRootValue
99 * ```
100 *
101 * ## Custom RootValue Type
102 *
103 * ```yaml
104 * plugins
105 * config:
106 * rootValueType: ./my-types#MyRootValue
107 * ```
108 */
109 directiveContextTypes?: Array<string>;
110 /**
111 * @description Use this to set a custom type for a specific field `context` decorated by a directive.
112 * It will only affect the targeted resolvers.
113 * You can either use `Field.Path#ContextTypeName` or `Field.Path#ExternalFileName#ContextTypeName`
114 *
115 * ContextTypeName should by a generic Type that take the context or field context type as only type parameter.
116 *
117 * @exampleMarkdown
118 * ## Directive Context Extender
119 *
120 * ```yaml
121 * plugins
122 * config:
123 * directiveContextTypes:
124 * - myCustomDirectiveName#./my-file#CustomContextExtender
125 * ```
126 *
127 */
128 rootValueType?: string;
129 /**
130 * @description Adds a suffix to the imported names to prevent name clashes.
131 *
132 * @exampleMarkdown
133 * ```yaml
134 * plugins
135 * config:
136 * mapperTypeSuffix: Model
137 * ```
138 */
139 mapperTypeSuffix?: string;
140 /**
141 * @description Replaces a GraphQL type usage with a custom type, allowing you to return custom object from
142 * your resolvers.
143 * You can use both `module#type` and `module#namespace#type` syntax.
144 *
145 * @exampleMarkdown
146 * ## Custom Context Type
147 *
148 * ```yaml
149 * plugins
150 * config:
151 * mappers:
152 * User: ./my-models#UserDbObject
153 * Book: ./my-models#Collections#Book
154 * ```
155 */
156 mappers?: {
157 [typeName: string]: string;
158 };
159 /**
160 * @description Allow you to set the default mapper when it's not being override by `mappers` or generics.
161 * You can specify a type name, or specify a string in `module#type` or `module#namespace#type` format.
162 * The default value of mappers is the TypeScript type generated by `typescript` package.
163 *
164 * @exampleMarkdown
165 * ## Replace with any
166 *
167 * ```yaml
168 * plugins
169 * config:
170 * defaultMapper: any
171 * ```
172 *
173 * ## Custom Base Object
174 *
175 * ```yaml
176 * plugins
177 * config:
178 * defaultMapper: ./my-file#BaseObject
179 * ```
180 *
181 * ## Wrap default types with Partial
182 *
183 * You can also specify a custom wrapper for the original type, without overriding the original generated types, use `{T}` to specify the identifier. (for flow, use `$Shape<{T}>`)
184 *
185 * ```yaml
186 * plugins
187 * config:
188 * defaultMapper: Partial<{T}>
189 * ```
190 *
191 * ## Allow deep partial with `utility-types`
192 *
193 * ```yaml
194 * plugins
195 * plugins:
196 * - 'typescript'
197 * - 'typescript-resolvers'
198 * - add:
199 * content: "import { DeepPartial } from 'utility-types';"
200 * config:
201 * defaultMapper: DeepPartial<{T}>
202 * ```
203 */
204 defaultMapper?: string;
205 /**
206 * @description This will cause the generator to avoid using optionals (`?`),
207 * so all field resolvers must be implemented in order to avoid compilation errors.
208 * @default false
209 *
210 * @exampleMarkdown
211 * ## Override all definition types
212 *
213 * ```yaml
214 * generates:
215 * path/to/file.ts:
216 * plugins:
217 * - typescript
218 * - typescript-resolvers
219 * config:
220 * avoidOptionals: true
221 * ```
222 *
223 * ## Override only specific definition types
224 *
225 * ```yaml
226 * generates:
227 * path/to/file.ts:
228 * plugins:
229 * - typescript
230 * config:
231 * avoidOptionals:
232 * field: true
233 * inputValue: true
234 * object: true
235 * defaultValue: true
236 * ```
237 */
238 avoidOptionals?: boolean | AvoidOptionalsConfig;
239 /**
240 * @description Warns about unused mappers.
241 * @default true
242 *
243 * @exampleMarkdown
244 * ```yaml
245 * generates:
246 * path/to/file.ts:
247 * plugins:
248 * - typescript
249 * - typescript-resolvers
250 * config:
251 * showUnusedMappers: true
252 * ```
253 */
254 showUnusedMappers?: boolean;
255 /**
256 * @description Overrides the default value of enum values declared in your GraphQL schema, supported
257 * in this plugin because of the need for integration with `typescript` package.
258 * See documentation under `typescript` plugin for more information and examples.
259 */
260 enumValues?: EnumValuesMap;
261 /**
262 * @default Promise<T> | T
263 * @description Allow you to override `resolverTypeWrapper` definition.
264 */
265 resolverTypeWrapperSignature?: string;
266 /**
267 * @default false
268 * @description Supports Apollo Federation
269 */
270 federation?: boolean;
271 /**
272 * @default true
273 * @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`.
274 *
275 * @exampleMarkdown
276 * ## Disable enum prefixes
277 *
278 * ```yaml
279 * config:
280 * typesPrefix: I
281 * enumPrefix: false
282 * ```
283 */
284 enumPrefix?: boolean;
285 /**
286 * @default false
287 * @description Sets the `__resolveType` field as optional field.
288 */
289 optionalResolveType?: boolean;
290 /**
291 * @default false
292 * @description Generates immutable types by adding `readonly` to properties and uses `ReadonlyArray`.
293 */
294 immutableTypes?: boolean;
295 /**
296 * @default ''
297 * @description Prefixes all GraphQL related generated types with that value, as namespaces import.
298 * You can use this feature to allow separation of plugins to different files.
299 */
300 namespacedImportName?: string;
301 /**
302 * @default Resolvers
303 * @description Suffix we add to each generated type resolver.
304 */
305 resolverTypeSuffix?: string;
306 /**
307 * @default Resolvers
308 * @description The type name to use when exporting all resolvers signature as unified type.
309 */
310 allResolversTypeName?: string;
311 /**
312 * @type string
313 * @default '__'
314 * @description Defines the prefix value used for `__resolveType` and `__isTypeOf` resolvers.
315 * If you are using `mercurius-js`, please set this field to empty string for better compatibility.
316 */
317 internalResolversPrefix?: string;
318 /**
319 * @type boolean
320 * @default false
321 * @description Turning this flag to `true` will generate resolver signature that has only `resolveType` for interfaces, forcing developers to write inherited type resolvers in the type itself.
322 */
323 onlyResolveTypeForInterfaces?: boolean;
324 /**
325 * @ignore
326 */
327 directiveResolverMappings?: Record<string, string>;
328}
329export declare type ResolverTypes = {
330 [gqlType: string]: string;
331};
332export declare type ResolverParentTypes = {
333 [gqlType: string]: string;
334};
335export declare type GroupedMappers = Record<string, {
336 identifier: string;
337 asDefault?: boolean;
338}[]>;
339declare type FieldContextTypeMap = Record<string, ParsedMapper>;
340export declare class BaseResolversVisitor<TRawConfig extends RawResolversConfig = RawResolversConfig, TPluginConfig extends ParsedResolversConfig = ParsedResolversConfig> extends BaseVisitor<TRawConfig, TPluginConfig> {
341 private _schema;
342 protected _parsedConfig: TPluginConfig;
343 protected _declarationBlockConfig: DeclarationBlockConfig;
344 protected _collectedResolvers: {
345 [key: string]: string;
346 };
347 protected _collectedDirectiveResolvers: {
348 [key: string]: string;
349 };
350 protected _variablesTransformer: OperationVariablesToObject;
351 protected _usedMappers: {
352 [key: string]: boolean;
353 };
354 protected _resolversTypes: ResolverTypes;
355 protected _resolversParentTypes: ResolverParentTypes;
356 protected _rootTypeNames: Set<string>;
357 protected _globalDeclarations: Set<string>;
358 protected _federation: ApolloFederation;
359 protected _hasScalars: boolean;
360 protected _hasFederation: boolean;
361 protected _fieldContextTypeMap: FieldContextTypeMap;
362 protected _directiveContextTypesMap: FieldContextTypeMap;
363 private _directiveResolverMappings;
364 private _shouldMapType;
365 constructor(rawConfig: TRawConfig, additionalConfig: TPluginConfig, _schema: GraphQLSchema, defaultScalars?: NormalizedScalarsMap);
366 getResolverTypeWrapperSignature(): string;
367 protected shouldMapType(type: GraphQLNamedType, duringCheck?: string[]): boolean;
368 convertName(node: ASTNode | string, options?: BaseVisitorConvertOptions & ConvertOptions, applyNamespacedImport?: boolean): string;
369 protected createResolversFields(applyWrapper: (str: string) => string, clearWrapper: (str: string) => string, getTypeToUse: (str: string) => string, shouldInclude?: (type: GraphQLNamedType) => boolean): ResolverTypes;
370 protected replaceFieldsInType(typeName: string, relevantFields: {
371 addOptionalSign: boolean;
372 fieldName: string;
373 replaceWithType: string;
374 }[]): string;
375 protected applyMaybe(str: string): string;
376 protected applyResolverTypeWrapper(str: string): string;
377 protected clearMaybe(str: string): string;
378 protected clearResolverTypeWrapper(str: string): string;
379 protected wrapWithArray(t: string): string;
380 protected createFieldContextTypeMap(): FieldContextTypeMap;
381 protected createDirectivedContextType(): FieldContextTypeMap;
382 buildResolversTypes(): string;
383 buildResolversParentTypes(): string;
384 get schema(): GraphQLSchema;
385 get defaultMapperType(): string;
386 get unusedMappers(): string[];
387 get globalDeclarations(): string[];
388 protected isMapperImported(groupedMappers: GroupedMappers, identifier: string, source: string): boolean;
389 get mappersImports(): string[];
390 setDeclarationBlockConfig(config: DeclarationBlockConfig): void;
391 setVariablesTransformer(variablesTransfomer: OperationVariablesToObject): void;
392 hasScalars(): boolean;
393 hasFederation(): boolean;
394 getRootResolver(): string;
395 protected formatRootResolver(schemaTypeName: string, resolverType: string, declarationKind: DeclarationKind): string;
396 getAllDirectiveResolvers(): string;
397 Name(node: NameNode): string;
398 ListType(node: ListTypeNode): string;
399 protected _getScalar(name: string): string;
400 NamedType(node: NamedTypeNode): string;
401 NonNullType(node: NonNullTypeNode): string;
402 protected markMapperAsUsed(name: string): void;
403 protected getTypeToUse(name: string): string;
404 protected getParentTypeToUse(name: string): string;
405 protected getParentTypeForSignature(_node: FieldDefinitionNode): string;
406 protected transformParentGenericType(parentType: string): string;
407 FieldDefinition(node: FieldDefinitionNode, key: string | number, parent: any): (parentName: string) => string | null;
408 private getFieldContextType;
409 private getContextType;
410 protected applyRequireFields(argsType: string, fields: InputValueDefinitionNode[]): string;
411 protected applyOptionalFields(argsType: string, _fields: readonly InputValueDefinitionNode[]): string;
412 ObjectTypeDefinition(node: ObjectTypeDefinitionNode): string;
413 UnionTypeDefinition(node: UnionTypeDefinitionNode, key: string | number, parent: any): string;
414 ScalarTypeDefinition(node: ScalarTypeDefinitionNode): string;
415 DirectiveDefinition(node: DirectiveDefinitionNode, key: string | number, parent: any): string;
416 protected buildEnumResolverContentBlock(_node: EnumTypeDefinitionNode, _mappedEnumType: string): string;
417 protected buildEnumResolversExplicitMappedValues(_node: EnumTypeDefinitionNode, _valuesMapping: {
418 [valueName: string]: string | number;
419 }): string;
420 EnumTypeDefinition(node: EnumTypeDefinitionNode): string;
421 InterfaceTypeDefinition(node: InterfaceTypeDefinitionNode): string;
422 SchemaDefinition(): any;
423}
424export {};