@@ -30,6 +30,7 @@ export const generator: Generator = {
30
30
RootType : renderRootType ,
31
31
SchemaType : renderSchemaInterface ,
32
32
Main : renderMainMethod ,
33
+ Header : renderHeader ,
33
34
}
34
35
35
36
const scalarMapping = {
@@ -40,24 +41,112 @@ const scalarMapping = {
40
41
Boolean : 'boolean'
41
42
}
42
43
44
+ function renderHeader ( schema : string ) : string {
45
+ return `import { FragmentReplacements } from 'graphcool-binding/dist/src/extractFragmentReplacements';
46
+ import { GraphcoolLink } from 'graphcool-binding/dist/src/GraphcoolLink';
47
+ import { buildFragmentInfo, buildTypeLevelInfo } from 'graphcool-binding/dist/src/prepareInfo';
48
+ import { GraphQLResolveInfo, GraphQLSchema } from 'graphql';
49
+ import { GraphQLClient } from 'graphql-request';
50
+ import { SchemaCache } from 'graphql-schema-cache';
51
+ import { delegateToSchema } from 'graphql-tools';
52
+ import { sign } from 'jsonwebtoken';
53
+
54
+ // -------------------
55
+ // This should be in graphcool-binding
56
+ interface BindingOptions {
57
+ fragmentReplacements?: FragmentReplacements
58
+ endpoint: string
59
+ secret: string
60
+ }
61
+
62
+ interface BaseBindingOptions extends BindingOptions {
63
+ typeDefs: string
64
+ }
65
+
66
+ const schemaCache = new SchemaCache()
67
+
68
+ class BaseBinding {
69
+ private remoteSchema: GraphQLSchema
70
+ private fragmentReplacements: FragmentReplacements
71
+ private graphqlClient: GraphQLClient
72
+
73
+ constructor({
74
+ typeDefs,
75
+ endpoint,
76
+ secret,
77
+ fragmentReplacements} : BaseBindingOptions) {
78
+
79
+ fragmentReplacements = fragmentReplacements || {}
80
+
81
+ const token = sign({}, secret)
82
+ const link = new GraphcoolLink(endpoint, token)
83
+
84
+ this.remoteSchema = schemaCache.makeExecutableSchema({
85
+ link,
86
+ typeDefs,
87
+ key: endpoint,
88
+ })
89
+
90
+ this.fragmentReplacements = fragmentReplacements
91
+
92
+ this.graphqlClient = new GraphQLClient(endpoint, {
93
+ headers: { Authorization: \`Bearer \${token}\` },
94
+ })
95
+ }
96
+
97
+ delegate<T>(operation: 'query' | 'mutation', prop: string, args, info?: GraphQLResolveInfo | string): Promise<T> {
98
+ if (!info) {
99
+ info = buildTypeLevelInfo(prop, this.remoteSchema, operation)
100
+ } else if (typeof info === 'string') {
101
+ info = buildFragmentInfo(prop, this.remoteSchema, operation, info)
102
+ }
103
+
104
+ return delegateToSchema(
105
+ this.remoteSchema,
106
+ this.fragmentReplacements,
107
+ operation,
108
+ prop,
109
+ args || {},
110
+ {},
111
+ info,
112
+ )
113
+ }
114
+
115
+ async request<T = any>(
116
+ query: string,
117
+ variables?: { [key: string]: any },
118
+ ): Promise<T> {
119
+ return this.graphqlClient.request<T>(query, variables)
120
+ }
121
+ }
122
+ // -------------------
123
+
124
+ const typeDefs = \`
125
+ ${ schema } \``
126
+ }
127
+
43
128
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 ( ) ) }
129
+ return `export class Binding extends BaseBinding {
130
+
131
+ constructor({ endpoint, secret, fragmentReplacements} : BindingOptions) {
132
+ super({ typeDefs, endpoint, secret, fragmentReplacements});
133
+ }
134
+
135
+ query: Query = {
136
+ ${ renderMainMethodFields ( 'query' , queryType . getFields ( ) ) }
137
+ }${ mutationType ? `
138
+
139
+ mutation: Mutation = {
140
+ ${ renderMainMethodFields ( 'mutation' , mutationType . getFields ( ) ) }
53
141
}` : '' }
54
142
}`
55
143
}
56
144
57
- function renderMainMethodFields ( fields : GraphQLFieldMap < any , any > ) : string {
145
+
146
+ function renderMainMethodFields ( operation : string , fields : GraphQLFieldMap < any , any > ) : string {
58
147
return Object . keys ( fields ) . map ( f => {
59
148
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 */ } `
149
+ return ` ${ field . name } : (args, info): Promise< ${ renderFieldType ( field . type ) } ${ ! isNonNullType ( field . type ) ? ' | null' : '' } > => super.delegate(' ${ operation } ', ' ${ field . name } ', args, info) `
61
150
} ) . join ( ',\n' )
62
151
}
63
152
@@ -77,7 +166,7 @@ ${type.getValues().map(e => ` ${e.name} = '${e.value}'`).join(',\n')}
77
166
function renderRootType ( type : GraphQLObjectType ) : string {
78
167
const fieldDefinition = Object . keys ( type . getFields ( ) ) . map ( f => {
79
168
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' : '' } `
169
+ return ` ${ field . name } : (args: {${ field . args . length > 0 ? ' ' : '' } ${ field . args . map ( f => `${ renderFieldName ( f ) } : ${ renderFieldType ( f . type ) } ` ) . join ( ', ' ) } ${ field . args . length > 0 ? ' ' : '' } }, info?: GraphQLResolveInfo | string ) => Promise< ${ renderFieldType ( field . type ) } ${ ! isNonNullType ( field . type ) ? ' | null' : '' } > `
81
170
} ) . join ( '\n' )
82
171
83
172
return renderInterfaceWrapper ( type . name , type . description , type . getInterfaces ( ) , fieldDefinition )
0 commit comments