Skip to content
This repository was archived by the owner on May 10, 2018. It is now read-only.

Commit 71142e6

Browse files
committed
Included binding class in generated code
1 parent b354300 commit 71142e6

File tree

5 files changed

+109
-15
lines changed

5 files changed

+109
-15
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-static-binding",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "Generate static binding files for a GraphQL schema",
55
"main": "dist/index.js",
66
"typings": "dist/index.d.ts",

src/generators/javascript.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { Generator } from '../types'
2222

2323
export const generator: Generator = {
2424
Main: renderMainMethod,
25+
Header: () => '',
2526
}
2627

2728
function renderMainMethod(queryType: GraphQLObjectType, mutationType?: GraphQLObjectType | null, subscriptionType?: GraphQLObjectType | null) {

src/generators/typescript.ts

Lines changed: 101 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const generator: Generator = {
3030
RootType: renderRootType,
3131
SchemaType: renderSchemaInterface,
3232
Main: renderMainMethod,
33+
Header: renderHeader,
3334
}
3435

3536
const 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+
43128
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())}
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')}
77166
function 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)

src/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ export function generateCode(schema: string, generator: Generator): string {
1818
.filter(typeName => ast.getSubscriptionType() ? typeName !== ast.getSubscriptionType()!.name : true)
1919
.sort((a,b) => ast.getType(a).constructor.name < ast.getType(b).constructor.name ? -1 : 1)
2020

21+
// Special case 4: header
22+
const generatedClass = [generator.Header(schema)]
23+
2124
// Process all types
22-
const generatedClass = typeNames.map(typeName => {
25+
generatedClass.push(...typeNames.map(typeName => {
2326
const type = ast.getTypeMap()[typeName]
2427
return generator[type.constructor.name] ? generator[type.constructor.name](type) : null
25-
})
28+
}))
2629

2730
// Special case 1: generate schema interface
2831
if (generator.SchemaType) {

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { GraphQLObjectType, GraphQLUnionType, GraphQLInputObjectType, GraphQLSca
22

33
export interface Generator {
44
Main: (queryType: GraphQLObjectType, mutationType?: GraphQLObjectType | null, subscriptionType?: GraphQLObjectType | null) => string,
5+
Header: (schema: string) => string,
56
SchemaType?: (queryType: GraphQLObjectType, mutationType?: GraphQLObjectType | null, subscriptionType?: GraphQLObjectType | null) => string,
67
RootType?: (type: GraphQLObjectType) => string,
78
GraphQLUnionType?: (type: GraphQLUnionType) => string,

0 commit comments

Comments
 (0)