@@ -30,6 +30,7 @@ export const generator: Generator = {
3030 RootType : renderRootType ,
3131 SchemaType : renderSchemaInterface ,
3232 Main : renderMainMethod ,
33+ Header : renderHeader ,
3334}
3435
3536const scalarMapping = {
@@ -40,24 +41,112 @@ const scalarMapping = {
4041 Boolean : 'boolean'
4142}
4243
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+
43128function 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 ( ) ) }
53141 }` : '' }
54142}`
55143}
56144
57- function renderMainMethodFields ( fields : GraphQLFieldMap < any , any > ) : string {
145+
146+ function renderMainMethodFields ( operation : string , fields : GraphQLFieldMap < any , any > ) : string {
58147 return Object . keys ( fields ) . map ( f => {
59148 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) `
61150 } ) . join ( ',\n' )
62151}
63152
@@ -77,7 +166,7 @@ ${type.getValues().map(e => ` ${e.name} = '${e.value}'`).join(',\n')}
77166function renderRootType ( type : GraphQLObjectType ) : string {
78167 const fieldDefinition = Object . keys ( type . getFields ( ) ) . map ( f => {
79168 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' : '' } > `
81170 } ) . join ( '\n' )
82171
83172 return renderInterfaceWrapper ( type . name , type . description , type . getInterfaces ( ) , fieldDefinition )
0 commit comments