1+ import {
2+ GraphQLUnionType ,
3+ GraphQLWrappingType ,
4+ GraphQLObjectType ,
5+ GraphQLInputObjectType ,
6+ GraphQLInputField ,
7+ GraphQLField ,
8+ GraphQLInputType ,
9+ GraphQLOutputType ,
10+ GraphQLScalarType ,
11+ GraphQLNamedType ,
12+
13+ isNonNullType ,
14+ isListType ,
15+ GraphQLFieldMap ,
16+ GraphQLEnumType ,
17+ GraphQLType ,
18+ GraphQLInterfaceType ,
19+ } from 'graphql'
20+
21+ import { Generator } from '../types'
22+
23+ export const generator : Generator = {
24+ GraphQLUnionType : renderUnionType ,
25+ GraphQLObjectType : renderObjectType ,
26+ GraphQLInputObjectType : renderObjectType ,
27+ GraphQLScalarType : renderScalarType ,
28+ GraphQLEnumType : renderEnumType ,
29+ GraphQLInterfaceType : renderObjectType ,
30+ RootType : renderRootType ,
31+ SchemaType : renderSchemaInterface ,
32+ Main : renderMainMethod ,
33+ }
34+
35+ const scalarMapping = {
36+ Int : 'number' ,
37+ String : 'string' ,
38+ ID : 'string | number' ,
39+ Float : 'number' ,
40+ Boolean : 'boolean'
41+ }
42+
43+ function renderMainMethod ( queryType : GraphQLObjectType , mutationType ?: GraphQLObjectType | null , subscriptionType ?: GraphQLObjectType | null ) {
44+ return `export const binding: Schema = {
45+ query: {
46+ ${ renderMainMethodFields ( queryType . getFields ( ) ) }
47+ }${ mutationType ? `,
48+ mutation: {
49+ ${ renderMainMethodFields ( mutationType . getFields ( ) ) }
50+ }` : '' } ${ subscriptionType ? `,
51+ subscription: {
52+ ${ renderMainMethodFields ( subscriptionType . getFields ( ) ) }
53+ }` : '' }
54+ }`
55+ }
56+
57+ function renderMainMethodFields ( fields : GraphQLFieldMap < any , any > ) : string {
58+ return Object . keys ( fields ) . map ( f => {
59+ const field = fields [ f ]
60+ return ` ${ field . name } : (args, info): ${ renderFieldType ( field . type ) } ${ ! isNonNullType ( field . type ) ? ' | null' : '' } => { return /* TODO: Get actual implementation here from graphql-binding */ }`
61+ } ) . join ( ',\n' )
62+ }
63+
64+ function renderScalarType ( type : GraphQLScalarType ) : string {
65+ return `${ type . description ? `/*
66+ ${ type . description }
67+ */
68+ ` : '' } export type ${ type . name } = ${ scalarMapping [ type . name ] || 'string' } `
69+ }
70+
71+ function renderEnumType ( type : GraphQLEnumType ) : string {
72+ return `${ renderDescription ( type . description ) } export enum ${ type . name } {
73+ ${ type . getValues ( ) . map ( e => ` ${ e . name } = '${ e . value } '` ) . join ( ',\n' ) }
74+ }`
75+ }
76+
77+ function renderRootType ( type : GraphQLObjectType ) : string {
78+ const fieldDefinition = Object . keys ( type . getFields ( ) ) . map ( f => {
79+ const field = type . getFields ( ) [ f ]
80+ return ` ${ field . name } : (args: {${ field . args . length > 0 ? ' ' : '' } ${ field . args . map ( f => `${ renderFieldName ( f ) } : ${ renderFieldType ( f . type ) } ` ) . join ( ', ' ) } ${ field . args . length > 0 ? ' ' : '' } }, info: any) => ${ renderFieldType ( field . type ) } ${ ! isNonNullType ( field . type ) ? ' | null' : '' } `
81+ } ) . join ( '\n' )
82+
83+ return renderInterfaceWrapper ( type . name , type . description , type . getInterfaces ( ) , fieldDefinition )
84+ }
85+
86+ function renderUnionType ( type : GraphQLUnionType ) : string {
87+ return `${ renderDescription ( type . description ) } export type ${ type . name } = ${ type . getTypes ( ) . map ( t => t . name ) . join ( ' | ' ) } `
88+ }
89+
90+ function renderObjectType ( type : GraphQLObjectType | GraphQLInputObjectType | GraphQLInterfaceType ) : string {
91+ const fieldDefinition = Object . keys ( type . getFields ( ) ) . map ( f => {
92+ const field = type . getFields ( ) [ f ]
93+ return ` ${ renderFieldName ( field ) } : ${ renderFieldType ( field . type ) } `
94+ } ) . join ( '\n' )
95+
96+ let interfaces : GraphQLInterfaceType [ ] = [ ]
97+ if ( type instanceof GraphQLObjectType ) {
98+ interfaces = type . getInterfaces ( )
99+ }
100+
101+ return renderInterfaceWrapper ( type . name , type . description , interfaces , fieldDefinition )
102+ }
103+
104+
105+
106+ function renderFieldName ( field : GraphQLInputField | GraphQLField < any , any > ) {
107+ return `${ field . name } ${ isNonNullType ( field . type ) ? '' : '?' } `
108+ }
109+
110+ function renderFieldType ( type : GraphQLInputType | GraphQLOutputType ) {
111+ if ( isNonNullType ( type ) ) {
112+ return renderFieldType ( ( type as GraphQLWrappingType ) . ofType )
113+ }
114+ if ( isListType ( type ) ) {
115+ return `Array<${ renderFieldType ( ( type as GraphQLWrappingType ) . ofType ) } >`
116+ }
117+ return ( type as GraphQLNamedType ) . name
118+ }
119+
120+ function renderSchemaInterface ( queryType : GraphQLObjectType , mutationType ?: GraphQLObjectType | null , subscriptionType ?: GraphQLObjectType | null ) {
121+ return `export interface Schema {
122+ query: ${ queryType . name }
123+ ${ mutationType ? ` mutation: ${ mutationType . name }
124+ ` : '' } ${ subscriptionType ? ` subscription: ${ subscriptionType . name }
125+ ` : '' } }`
126+ }
127+
128+ function renderInterfaceWrapper ( typeName : string , typeDescription : string , interfaces : GraphQLInterfaceType [ ] , fieldDefinition : string ) : string {
129+ return `${ renderDescription ( typeDescription ) } export interface ${ typeName } ${ interfaces . length > 0 ? ` extends ${ interfaces . map ( i => i . name ) . join ( ', ' ) } ` : '' } {
130+ ${ fieldDefinition }
131+ }`
132+ }
133+
134+ function renderDescription ( description ?: string ) {
135+ return `${ description ? `/*
136+ ${ description }
137+ */
138+ ` : '' } `
139+ }
0 commit comments