Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Extending Graphback to support various use cases outside the core package #635

Closed
wtrocki opened this issue Jan 15, 2020 · 5 comments
Closed
Assignees

Comments

@wtrocki
Copy link
Contributor

wtrocki commented Jan 15, 2020

Motivation

Currently to make a change in graphback users need to assses and change elements in Graphback core that might or might not break the entire ecosystem of plugins.
We have done some separation of concerns for architecture but overall customization and maintenance is not easy as we initially anticipated. That is why we need to come up with the right format and document it properly. At the moment we cannot effectively provide solutions for various use cases without including them in the core.

Suggested changes

  1. Schema driven

Instead of parsing model and passing customized objects to the entire ecosystem of plugins we should pass generated schema to every plugin itself.
This will allow users to add their own directives and annotations and allow customization cases that the core team never anticipated.

  1. Opt-in instead of opt-out model

Instead of assuming that every Type needs CRUD resolvers developers can simply mark types in their schema as model. This approach will allow better support for various graphql patterns where developers need to exclude lots of types etc.

  1. Document architecture of the plugins and describe every plugin similar to graphql-code-generator

  2. Use GraphQL Config for each plugin separately

https://graphql-config.com/docs/introduction

  1. Graphback package as an opinionated manager for all available plugins and their options.
    Working with so many packages will be really hard. We need to make things easy by integrating them along with graphql config to minimize the amount of code that is needed and also simplify cli integration

  2. Schema generation should utilize print schema and merge the CRUD model with existing schema instead of rebuilding schema from scratch.

  3. We are going to sacrifice performance and visit every node in the schema for each plugin.
    We can reuse visitors from the core and common annotation processors.
    Each individual plugin can also

  4. Important change each plugin will get full schema but it can also append/merge stuff and modify schema. The order of the plugins will matter. For example, we can have plugin that will remove annotations in the resulting schema as last step etc. Each plugin will return schema instance that will need to be passed to the next step (this is different to how graphql-code-generator works)

Areas to focus on

  1. Investigate the common set of the annotations that are currently in db namespace that should be shared across the plugins
    @craicoverflow

  2. Use generated schema as an input source for every plugin.
    One plugin at the time.
    @wtrocki

  3. Introduce model annotation. Migrate crud annotations into a single model annotations for simplicity. Investigate how model annotation will work with relationships.
    @wtrocki

  4. Introduce GraphQL Config in Graphback

  5. Refactor schema plugin to print schema instead of the building using core
    @wtrocki

  6. Replace core with the common set of the visitors that can be reused across the plugins

  7. Investigate and test the relationship models

  8. Interfaces/Scalar support

  9. Add basic schema validation for generated schema

  10. Reevaluate support for custom methods and out of the box queries
    @wtrocki

Let's create individual issues once we get agreement on this approach

@wtrocki wtrocki pinned this issue Jan 15, 2020
@wtrocki wtrocki changed the title Extending Graphback to support various use cases outside the core Extending Graphback to support various use cases outside the core package Jan 15, 2020
@wtrocki
Copy link
Contributor Author

wtrocki commented Jan 15, 2020

TL;DR We are trying to make Graphback work exactly how GraphQL-Code-Generator works.
The initial idea of using a common visitor before each plugin is not flexible and introduces many issues.

This is step 2 to make Graphback work like Codegen does.
We learned this the hard way by trying to integrate graphback into existing examples and not being able to support things like scalars etc. Additionally, our community were interested in migration from prisma #630 that should be fairly straightforward and clear to community after we put those changes in place.

CC @craicoverflow @darahayes @ardatan @ankitjena

@wtrocki wtrocki self-assigned this Jan 15, 2020
@craicoverflow
Copy link

craicoverflow commented Jan 16, 2020

1. Opt-in instead of opt-out model

Instead of assuming that every Type needs CRUD resolvers developers can simply mark types in their schema as model. This approach will allow better support for various graphql patterns where developers need to exclude lots of types etc.

Would types marked as "model" represent database tables and non-model be used for non-db types?

1. Document architecture of the plugins and describe every plugin similar to graphql-code-generator

2. Use GraphQL Config for each plugin separately

https://graphql-config.com/docs/introduction

So with this the user could remove the codegenResolvers plugin (as an example) which would only generate the schema and client code. Wouldn't this lead to the code generation workflow breaking if one or more of the plugins was to be removed from the config?

2. Schema generation should utilize print schema and merge the CRUD model with existing schema instead of rebuilding schema from scratch.

graphql/graphql-js#869 (comment) - We will have to see if this works for us in practice - it looks like printSchema loses some information from the schema (directives).

3. We are going to sacrifice performance and visit every node in the schema for each plugin.
   We can reuse visitors from the core and common annotation processors.

This is fine as performance will only be sacrificed at generation phase and won't affect application performance.

   Each individual plugin can also

Did you forget to finish this?

4. **Important change** each plugin will get full schema but it can also append/merge stuff and modify schema. The order of the plugins will matter. For example, we can have plugin that will remove annotations in the resulting schema as last step etc. Each plugin will return schema instance that will need to be passed to the next step (this is different to how graphql-code-generator works)

If plugin definition order in config matters this could get really messy and difficult for the end user to configure.

Areas to focus on

1. Investigate the common set of the annotations that are currently in db namespace that should be shared across the plugins

2. Use generated schema as an input source for every plugin.
   One plugin at the time.

If every plugin depends on the generated schema then should the schema generation phase happen outside (before) the plugin chain?

3. Introduce model annotation. Migrate crud annotations into a single model annotations for simplicity. Investigate how model annotation will work with relationships.

I like this. Would we also migrate some @db.* annotations to the @model annotation?

4. Introduce GraphQL Config in Graphback

5. Refactor schema plugin to print schema instead of the building using core

6. Replace core with the common set of the visitors that can be reused across the plugins

7. Investigate and test the relationship models

8. Interfaces/Scalar support

9. Add basic schema validation for generated schema

10. Reevaluate support for custom methods and out of the box queries

Let's create individual issues once we get agreement on this approach

@craicoverflow craicoverflow self-assigned this Jan 16, 2020
@wtrocki
Copy link
Contributor Author

wtrocki commented Jan 16, 2020

Would types marked as "model" represent database tables and non-model be used for non-db types?

Yes. This will allow us to introduce rest annotations and handlers much easier :D

So with this the user could remove the codegenResolvers plugin (as an example) which would only generate the schema and client code. Wouldn't this lead to the code generation workflow breaking if one or more of the plugins was to be removed from the config?

Graphback will be the ultimate place that joins them all into a single element.
Users will not interact with it - only plugin creators that can add things

graphql/graphql-js#869 (comment) - We will have to see if this works for us in practice - it looks like printSchema loses some information from the schema (directives).

We going to use graphql-tools for merging and printing. Example:

https://github.com/ardatan/graphql-toolkit/blob/068c39c0fe1c0d6d37704a21c14affbae2c491a3/packages/common/src/print-schema-with-directives.ts#L6

This is fine as performance will only be sacrificed at generation phase and won't affect application performance.

For runtime cases, it will incur a slower application start.

I like this. Would we also migrate some @db.* annotations to the @model annotation?

We need to clasify db annotations that can affect more than just db and move them under some common namespace or we can use some db ones in other generators

@wtrocki
Copy link
Contributor Author

wtrocki commented Jan 16, 2020

If every plugin depends on the generated schema then should the schema generation phase happen outside (before) the plugin chain?

Yes. That is my current focus to see what are the challenges of that approach and to validate it on the top level.

If plugin definition order in config matters this could get really messy and difficult for the end user to configure.

End users will not need to configure it. This is for contributors wanting to bring their own plugins etc. We will have graphback giving opiniated version of it. They will not depend on each other.

They will just be able to add things to the schema. This is not new idea - works pretty much like: https://aws-amplify.github.io/docs/cli-toolchain/graphql

Transform will:

  • Create some templates/source code/db whatever is needed
  • Can add back things to schema if needed
  • There is no depedency apart from some extreme use cases of transform that removes comments etc.

@wtrocki
Copy link
Contributor Author

wtrocki commented Feb 12, 2020

Implemented and available on master. See #675

@wtrocki wtrocki closed this as completed Feb 12, 2020
@wtrocki wtrocki unpinned this issue Feb 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants