Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Commit fb31ba7

Browse files
author
Jason Kuhrt
authored
feat(gg): simplify and make safer __resolveType (#411)
* feat(gg): simplify and make safer resolver type resovler Safer because: - strings constants are used to specifiy which graphql objects names may be returned. - null cannot be returned - undefined cannot be returned Simpler because: - no nesting of type-generics - only permits returning names of graphql objects (not objects) closes #409
1 parent 039fbe9 commit fb31ba7

File tree

6 files changed

+69
-40
lines changed

6 files changed

+69
-40
lines changed

packages/graphqlgen/src/generators/common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ const array = (
226226
return config.innerUnion ? `${innerType}[]` : `Array<${innerType}>`
227227
}
228228

229-
const union = (types: string[]): string => {
229+
export const union = (types: string[]): string => {
230230
return types.join(' | ')
231231
}
232232

packages/graphqlgen/src/generators/flow-generator.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
createInterfacesMap,
2525
createUnionsMap,
2626
} from './common'
27+
import { renderTypeResolveTypeResolver } from './ts-generator'
2728

2829
export function format(code: string, options: prettier.Options = {}) {
2930
try {
@@ -76,11 +77,9 @@ export function generate(args: GenerateArgs): string {
7677

7778
const interfacesMap = createInterfacesMap(args.interfaces)
7879
const unionsMap = createUnionsMap(args.unions)
79-
const hasPolymorphicObjects =
80-
Object.keys(interfacesMap).length > 0 || Object.keys(unionsMap).length > 0
8180

8281
return `\
83-
${renderHeader(args, { hasPolymorphicObjects })}
82+
${renderHeader(args)}
8483
8584
${renderEnums(args)}
8685
@@ -97,14 +96,7 @@ export function generate(args: GenerateArgs): string {
9796
`
9897
}
9998

100-
type HeaderOptions = {
101-
hasPolymorphicObjects?: boolean
102-
}
103-
104-
function renderHeader(
105-
args: GenerateArgs,
106-
{ hasPolymorphicObjects = false }: HeaderOptions = {},
107-
): string {
99+
function renderHeader(args: GenerateArgs): string {
108100
const modelsToImport = Object.keys(args.modelMap).map(k => args.modelMap[k])
109101
const modelsByImportPaths = groupModelsNameByImportPath(modelsToImport)
110102

@@ -117,9 +109,7 @@ function renderHeader(
117109
)
118110
.join(os.EOL)
119111

120-
const graphQLImports = hasPolymorphicObjects
121-
? ['GraphQLResolveInfo', 'GraphQLTypeResolver']
122-
: ['GraphQLResolveInfo']
112+
const graphQLImports = ['GraphQLResolveInfo']
123113

124114
return `/* @flow */
125115
// Code generated by github.com/prisma/graphqlgen, DO NOT EDIT.
@@ -223,9 +213,7 @@ function renderUnionNamespace(
223213
): string {
224214
return `\
225215
export interface ${graphQLTypeObject.name}_Resolvers {
226-
__resolveType?: GraphQLTypeResolver<${graphQLTypeObject.types
227-
.map(interfaceType => getModelName(interfaceType, args.modelMap))
228-
.join(' | ')}, ${getContextName(args.context)}>;
216+
__resolveType?: ${renderTypeResolveTypeResolver(graphQLTypeObject, args)}
229217
}
230218
`
231219
}

packages/graphqlgen/src/generators/ts-generator.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
UnionsMap,
2424
createInterfacesMap,
2525
createUnionsMap,
26+
union,
2627
} from './common'
2728
import { TypeAliasDefinition } from '../introspection/types'
2829
import { upperFirst } from '../utils'
@@ -108,7 +109,7 @@ function renderHeader(
108109
{ hasPolymorphicObjects = false }: HeaderOptions = {},
109110
): string {
110111
const imports = hasPolymorphicObjects
111-
? ['GraphQLResolveInfo', 'GraphQLTypeResolver', 'GraphQLIsTypeOfFn']
112+
? ['GraphQLResolveInfo', 'GraphQLIsTypeOfFn']
112113
: ['GraphQLResolveInfo']
113114

114115
return `
@@ -237,24 +238,50 @@ function renderInterfaceNamespace(
237238
)}
238239
239240
export interface Type {
240-
__resolveType: GraphQLTypeResolver<${graphQLTypeObject.implementors
241-
.map(interfaceType => getModelName(interfaceType, args.modelMap))
242-
.join(' | ')}, ${getContextName(args.context)}>;
241+
__resolveType: ${renderTypeResolveTypeResolver(graphQLTypeObject, args)}
243242
}
244243
}
245244
`
246245
}
247246

247+
export const renderTypeResolveTypeResolver = (
248+
abstractType: GraphQLInterfaceObject | GraphQLUnionObject,
249+
args: GenerateArgs,
250+
): string => {
251+
const modelNames: string[] = []
252+
const gqlObjectNameTypes: string[] = []
253+
const gqlObjects =
254+
abstractType.kind === 'interface'
255+
? abstractType.implementors
256+
: abstractType.types
257+
258+
for (const gqlObj of gqlObjects) {
259+
modelNames.push(getModelName(gqlObj, args.modelMap))
260+
gqlObjectNameTypes.push(renderStringConstant(gqlObj.name))
261+
}
262+
263+
return `
264+
(
265+
value: ${union(modelNames)},
266+
context: ${getContextName(args.context)},
267+
info: GraphQLResolveInfo
268+
) => ${resolverReturnType(union(gqlObjectNameTypes))}
269+
`
270+
}
271+
272+
const renderStringConstant = (x: unknown) => `"${x}"`
273+
248274
function renderUnionNamespace(
249275
graphQLTypeObject: GraphQLUnionObject,
250276
args: GenerateArgs,
251277
): string {
252278
return `\
253279
export namespace ${graphQLTypeObject.name}Resolvers {
254280
export interface Type {
255-
__resolveType?: GraphQLTypeResolver<${graphQLTypeObject.types
256-
.map(interfaceType => getModelName(interfaceType, args.modelMap))
257-
.join(' | ')}, ${getContextName(args.context)}>;
281+
__resolveType?: ${renderTypeResolveTypeResolver(
282+
graphQLTypeObject,
283+
args,
284+
)}
258285
}
259286
}
260287
`
@@ -430,6 +457,7 @@ function renderResolverFunctionInterfaces(
430457
.join(os.EOL)
431458
}
432459

460+
// MARK
433461
function renderResolverFunctionInterface(
434462
field: GraphQLTypeField,
435463
type: GraphQLTypeObject,
@@ -468,10 +496,15 @@ function renderResolverFunctionInterface(
468496
}
469497

470498
return `
471-
export type ${resolverName} = ${resolverDefinition} => ${returnType} | Promise<${returnType}>
499+
export type ${resolverName} = ${resolverDefinition} => ${resolverReturnType(
500+
returnType,
501+
)}
472502
`
473503
}
474504

505+
const resolverReturnType = (returnType: string): string =>
506+
union([returnType, `Promise<${returnType}>`])
507+
475508
function renderResolverTypeInterface(
476509
type: GraphQLTypeObject | GraphQLInterfaceObject,
477510
modelMap: ModelMap,

packages/graphqlgen/src/source-helper.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ export type GraphQLEnumObject = {
8080

8181
export type GraphQLUnionObject = {
8282
name: string
83+
kind: 'union'
8384
type: GraphQLTypeDefinition
8485
types: GraphQLTypeDefinition[]
8586
}
8687

8788
export type GraphQLInterfaceObject = {
8889
name: string
90+
kind: 'interface'
8991
type: GraphQLTypeDefinition
9092
fields: GraphQLTypeField[]
9193
implementors: GraphQLTypeDefinition[]
@@ -345,6 +347,7 @@ function extractGraphQLUnions(schema: GraphQLSchema) {
345347
})
346348
types.push({
347349
name: node.name,
350+
kind: 'union',
348351
type: {
349352
name: node.name,
350353
isObject: false,
@@ -380,6 +383,7 @@ function extractGraphQLInterfaces(
380383
if (implementorTypes.length) {
381384
interfaces.push({
382385
name: node.name,
386+
kind: 'interface',
383387
type: {
384388
name: node.name,
385389
isObject: false,

packages/graphqlgen/tests/flow/__snapshots__/basic.test.ts.snap

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ exports[`basic union 1`] = `
613613
"/* @flow */
614614
// Code generated by github.com/prisma/graphqlgen, DO NOT EDIT.
615615
616-
import type { GraphQLResolveInfo, GraphQLTypeResolver } from \\"graphql\\";
616+
import type { GraphQLResolveInfo } from \\"graphql\\";
617617
import type { Student, Professor, User } from \\"../../fixtures/union/flow-types\\";
618618
type Context = any;
619619
@@ -719,7 +719,11 @@ export interface User_Resolvers {
719719
}
720720
721721
export interface UserType_Resolvers {
722-
__resolveType?: GraphQLTypeResolver<Student | Professor, Context>;
722+
__resolveType?: (
723+
value: Student | Professor,
724+
context: Context,
725+
info: GraphQLResolveInfo
726+
) => \\"Student\\" | \\"Professor\\" | Promise<\\"Student\\" | \\"Professor\\">;
723727
}
724728
725729
export interface Resolvers {

packages/graphqlgen/tests/typescript/__snapshots__/basic.test.ts.snap

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,7 @@ export const resolvers: Resolvers = {
339339
exports[`basic interface 1`] = `
340340
"// Code generated by github.com/prisma/graphqlgen, DO NOT EDIT.
341341

342-
import {
343-
GraphQLResolveInfo,
344-
GraphQLTypeResolver,
345-
GraphQLIsTypeOfFn
346-
} from \\"graphql\\";
342+
import { GraphQLResolveInfo, GraphQLIsTypeOfFn } from \\"graphql\\";
347343
import { Dimensions, Image, Video } from \\"../../../fixtures/interface/types\\";
348344
type Context = any;
349345

@@ -518,7 +514,11 @@ export namespace VideoResolvers {
518514

519515
export namespace MediaResolvers {
520516
export interface Type {
521-
__resolveType: GraphQLTypeResolver<Image | Video, Context>;
517+
__resolveType: (
518+
value: Image | Video,
519+
context: Context,
520+
info: GraphQLResolveInfo
521+
) => \\"Image\\" | \\"Video\\" | Promise<\\"Image\\" | \\"Video\\">;
522522
}
523523
}
524524

@@ -1106,11 +1106,7 @@ export const resolvers: Resolvers = {
11061106
exports[`basic union 1`] = `
11071107
"// Code generated by github.com/prisma/graphqlgen, DO NOT EDIT.
11081108

1109-
import {
1110-
GraphQLResolveInfo,
1111-
GraphQLTypeResolver,
1112-
GraphQLIsTypeOfFn
1113-
} from \\"graphql\\";
1109+
import { GraphQLResolveInfo, GraphQLIsTypeOfFn } from \\"graphql\\";
11141110
import { Student, Professor, User } from \\"../../fixtures/union/types\\";
11151111
type Context = any;
11161112

@@ -1225,7 +1221,11 @@ export namespace UserResolvers {
12251221

12261222
export namespace UserTypeResolvers {
12271223
export interface Type {
1228-
__resolveType?: GraphQLTypeResolver<Student | Professor, Context>;
1224+
__resolveType?: (
1225+
value: Student | Professor,
1226+
context: Context,
1227+
info: GraphQLResolveInfo
1228+
) => \\"Student\\" | \\"Professor\\" | Promise<\\"Student\\" | \\"Professor\\">;
12291229
}
12301230
}
12311231

0 commit comments

Comments
 (0)