-
-
Save craicoverflow/8c2631eda88771bff825700dad04bc3b to your computer and use it in GitHub Desktop.
import { GraphbackDataProvider, GraphbackPlugin } from "graphback" | |
import { DocumentNode, GraphQLSchema } from 'graphql' | |
import { IResolvers, PubSubEngine } from 'apollo-server-express' | |
import { PgKnexDBDataProvider } from '@graphback/runtime-knex' | |
import Knex from 'knex' | |
interface DataProviderModelMap { | |
[modelName: string]: GraphbackDataProvider | |
} | |
/** | |
* Graphback config that is define by the user in their API code. | |
* | |
* modelDefs: | |
* The input model that Graphback uses as input to create a GraphQL schema and resolvers | |
* schema: | |
* The schema if provided will be used instead of modelDefs. | |
* This is because schema can have more resolvers and other information | |
* resolvers: | |
* Supply your own resolvers and we will merge them with Graphback resolvers | |
* dataProviders: | |
* Provide your data providers with a mapping to your Model name | |
* Or provide one and it will be used for all | |
* pubSub: | |
* Provide your pubSub. This can be optional since users may not use subscriptions | |
* schemaPlugins: | |
* Users can provide an array of custom schema plugins | |
* They will be executed in the order they are in the array | |
*/ | |
interface GraphbackConfig { | |
modelDefs?: DocumentNode | DocumentNode[] | string | string[] | |
schema?: GraphQLSchema | |
resolvers?: IResolvers | IResolvers[] | |
dataProviders: DataProviderModelMap | GraphbackDataProvider | |
pubSub?: PubSubEngine | |
schemaPlugins?: GraphbackPlugin[] | |
} | |
function makeGraphback(config: GraphbackConfig) { | |
// do some work and return generated stuff | |
return { typeDefs: '', resolvers: {}, dataSources: {} } | |
} | |
const db = Knex.Config() | |
const postgresProvider = new PgKnexDBDataProvider(db) | |
const { typeDefs, resolvers, dataSources } = makeGraphback({ | |
modelDefs: ` | |
""" | |
@model | |
""" | |
type Note { | |
id: ID! | |
title: String | |
} | |
`, | |
dataProviders: postgresProvider | |
}) |
I typically see schema still being in the project as a file. WHY? because you need to see it to add your own resolvers.
So we would still need two steps in this case?
- Run graphback to generate schema file.
- run server and load schema string from file into GraphbackResolvers to build resolver context.
This might still be achievable without the need for a file if MongoResolvers actually wraps full runtime implementation and gives you everything:
const graphbackBuilder = new GraphbackResolvers({model, crudService, dbProvider});
resolvers.setDataSource('Note', customDbProvider);
const { schemaSDL, resolvers } = graphbackBuilder.build();
// 1. Execute schema plugins
// 2. Build resolvers with data sources from builder
// 3. Output built schema with resolvers
const apolloServer = new ApolloServer({
typeDefs: schemaSDL,
resolvers
});
We will give developers much more than just black box schema and resolvers. They can add this to their project etc.
Plus we actually giving developers starter templates - others do not provide that.
Our templates can ignore the fact of the custom schema/generated one, but people could still generate schema and work with it.
Like if we target to provide single method thing let's:
- Kill templates
- Kill services and datasources
Have 2 methods - createMongo
and createPostgres
, but that is not going to work for us as we need to have more integrations that sometimes will exclude each other.
https://graphql-mesh.com is another good example how those guys resolved similar problem - worth checking their api
Fair points
graphql-mesh.com is another good example how those guys resolved similar problem - worth checking their api
Their docs are incomplete, I only see YAML configs.
We will give developers much more than just black box schema and resolvers. They can add this to their project etc.
True, but developers want simplicity and should be able to start with a miminal config API, adding more if they need it.
Plus we actually giving developers starter templates - others do not provide that.
The fewer starter templates we provide, the better in a way. Shouldn't starter templates focus on the non-Graphback elements of the application, like Apollo versus GrahQL.js, Mongo versus Postgres, how developers organise their architecture (we could have a GraphQL modules template).
If we need to have a template for very specific differences in Graphback API it might mean that the API is too difficult to make simple changes without having to change it all?
We could combine both approaches, where the resolver building would still be abstracted into the API:
interface GraphbackConfig {
schema: GraphQLSchema
resolvers?: ResolverBuilder | ResolverBuilder[]
pubSub?: PubSubEngine
schemaPlugins?: GraphbackPlugin[]
}
const modelSchema = buildSchema(`
"""
@model
"""
type Note {
id: ID!
title: String
}
`)
const resolverBuilder = new PostgresResolverBuilder(modelSchema, {})
// very minimal Graphback configuration
const { schema, resolvers, dataSources } = makeGraphback({
schema: modelSchema,
resolvers: [resolverBuilder] // accepts multiple resolver builders and merges them after doing the building, making it easy to mix data sources
})
I typically see schema still being in the project as a file. WHY? because you need to see it to add your own resolvers. Then you merging graphback generated resolvers with your own resolvers and scalars and calling it a day.