Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Write GraphQL Schema to a File #3286

Closed
DimuthuMadushan opened this issue Aug 26, 2022 · 12 comments
Closed

Proposal: Write GraphQL Schema to a File #3286

DimuthuMadushan opened this issue Aug 26, 2022 · 12 comments
Assignees
Labels
module/graphql Issues related to Ballerina GraphQL module Points/1 Status/Accepted Accepted proposals Status/Implemented Implemented proposals Team/PCM Protocol connector packages related issues Type/NewFeature Type/Proposal

Comments

@DimuthuMadushan
Copy link

DimuthuMadushan commented Aug 26, 2022

Summary

The Ballerina GraphQL package generates the schema for a given Ballerina GraphQL service at the compile time. Currently, the generated schema is exposed to the outside only via introspection. This proposal is to write the generated schema to a file in GraphQL Schema Definition Language(SDL) that the users can access.

Goals

  • Export the GraphQL schema files using a GraphQL CLI command.

Motivation

Since the Ballerina GraphQL module uses the code-first approach, users can not have the generated schema from the service in Schema Definition Language(SDL). The only way to check the schema in SDL is by using a client tool (e.g., GraphQL Playground). Therefore, it’s essential to have a way to access the schema generated from the service. With this, the users will be able to access the schema and ensure the validity of the generated schema. Also, the file can be exported and used with any other GraphQL libraries without any issue since the schema is written in a language-agnostic way.

Description

The SDL schema file generation can be done using the GraphQL CLI command. The GraphQL CLI tool gets the compilation of given GraphQL service to access the schema string. It extracts the annotated schema string from the syntax tree and deserializes it to the schema object. This schema object is used to generate the GraphQL SDL schema string using the SdlSchemaStringGenerator which is published in the GraphQL Commons package. The generated SDL schema string is written to a file and exported into the given path in the CLI command. When an error occurs during the SDL schema generation, a stderr message is logged in the console. The errors that don't have a specific location return (-1:-1,-1:-1) as the error location.

SDL schema string generator

The SDL Schema String Generator is a new component added to the GraphQL Commons package. It accepts the generated schema object and creates the schema string in GraphQL Schema Definition Language.

CLI command

The CLI command for the SDL file generation includes multiple parameters as follows.

$bal graphql [-i | --input] <graphql-service-file-path>
             [-o | --output] <output-location> 
             [-s | --service] <service-base-path>

1. graphql-service-file-path

The ballerina-service-file-path parameter specifies the path of the ballerina service file (e.g., graphql.bal) and is mandatory. If there are multiple GraphQL services included in the bal file, the command generates the schema for each graphql service.

2. output-location

The SDL schema file is exported into the location given as the output-location in the CLI command. This is an optional parameter. By default, the schema file is exported into the same directory where the bal command is executed.

3. service-base-path

The service-base-path can be used to specify the absolute service path of the GraphQL service(e.g., /gql). Then the schema is generated only for the service that has the matching absolute path. If no matching service is found, an error is returned. This is an optional parameter as the output-location.

Schema File

The schema file is written in GraphQL Schema Definition Language(SDL) with a name of the following format. The file extension is .graphql.

|--schema_<service-base-path>/<service-file-name>.<duplicate-count(optional)>.graphql

The service-base-path is a concatenation of base path segments by an underscore(e.g., “graphql_service”). The duplicate-count is appended to the name in order to distinguish the schema file when having multiple services with the same base path in a given service file. It is an optional segment in the file name.

Also, if there is a duplicate schema file in the output directory, a response message is displayed in the console to get a user input. It asks whether to override the existing file or generate a new file. Based on the user input, It decides whether to override the file or create a new file. If the user doesn’t want to override it, the duplicate-count is appended to the name of the newly generated schema file.

@DimuthuMadushan DimuthuMadushan added Points/1 Type/Proposal module/graphql Issues related to Ballerina GraphQL module Team/PCM Protocol connector packages related issues labels Aug 26, 2022
@DimuthuMadushan DimuthuMadushan added the Status/Active Proposals that are under review label Aug 26, 2022
@DimuthuMadushan DimuthuMadushan self-assigned this Aug 26, 2022
@DimuthuMadushan
Copy link
Author

@shafreenAnfar @ThisaruGuruge FYA

@ThisaruGuruge
Copy link
Member

ThisaruGuruge commented Sep 13, 2022

I have a couple of concerns here.

  • The schema is incomplete in the compiling phase due to the default value issue. We probably going to get the default values at the runtime and inject it into the generated schema, at least for some cases. We might have to consider this when writing the schema to a file.
  • There should be a way for the user to provide a custom name for the generated file. Maybe we can include a separate record (like grapiql config) here.
  • That brings the next question of whether the service config is the place to have this configuration as this is not directly related to the service from the Ballerina point of view.

Additionally, if we are to write the schema to a file, we should be eyeing to read it at the runtime and load the in-memory schema instead of writing the whole schema as an annotation. We should add that as a future plan. In that case, users may not be able to disable the file creation. (Or maybe we can create a temp file and delete it once we load the schema, we can decide later).

@shafreenAnfar any thoughts?

P.S.: I think we can come up with a better name than schemaFileGenEnabled, subjective matter though.

@shafreenAnfar
Copy link
Contributor

Good concerns.

In the case of openapi you can to do the following,

bal openapi -i /path/to/file.bal

I think we can do the same for gql as follows,

bal graphql -i /path/to/file.bal

The full set of configuration is as follows,

bal openapi [-i | --input] <ballerina-service-file-path> [--json]
            [-s | --service] <current-service-name>
            [-o | --output] <output-location>

@ThisaruGuruge
Copy link
Member

Good concerns.

In the case of openapi you can to do the following,

bal openapi -i /path/to/file.bal

I think we can do the same for gql as follows,

bal graphql -i /path/to/file.bal

The full set of configuration is as follows,

bal openapi [-i | --input] <ballerina-service-file-path> [--json]
            [-s | --service] <current-service-name>
            [-o | --output] <output-location>

I did not understand this configuration. Do we need to provide it when we running the service or building?

@shafreenAnfar
Copy link
Contributor

No it is a separate command, it is not part of the build command. Check the below link.

https://ballerina.io/learn/cli-documentation/openapi/

@ThisaruGuruge
Copy link
Member

Right. This looks good. But in this case, the user has to execute a separate command to generate the file, right?
In GraphQL, our plan is to generate this file when we compile the project. (in the future use the generated file to transfer the schema to runtime).
Apart from that, this approach looks better.

@DimuthuMadushan
Copy link
Author

Good concerns.

In the case of openapi you can to do the following,

bal openapi -i /path/to/file.bal

I think we can do the same for gql as follows,

bal graphql -i /path/to/file.bal

The full set of configuration is as follows,

bal openapi [-i | --input] <ballerina-service-file-path> [--json]
            [-s | --service] <current-service-name>
            [-o | --output] <output-location>
  1. These input values can be accessed only within the CLI tool. We won't be able to access those inside the GrpahQL compiler plugin. Therefore, we have to move the schema file generation logic to the CLI side which makes things a bit complex.

  2. If we move the file generation to the CLI side, we won't be able to resolve the default value issue(1st concern in @ThisaruGuruge's comment) since we are going to get those values at the runtime as mentioned in the comment.

But in this case, the user has to execute a separate command to generate the file, right?
In GraphQL, our plan is to generate this file when we compile the project. (in the future use the generated file to transfer the schema to runtime).

  1. If we are going to implement the above as a future plan, then these CLI commands will be useless since by default the schema file is generated when compiling the service.

Alternative approach: We can introduce two configurable variables inside the GraphQL module to get the inputs for enabling or disabling the schema file generation and the file name.

Ex: Configurable variables:

public configurable boolean schemaFileGenEnabled = true;
public configurable string schemaFileName = "";

Execution command:

bal run -- -Cballerina.graphql.schemaFileGenEnabled=true -Cballerina.graphql.schemaFileName=fileName

@shafreenAnfar @ThisaruGuruge any thoughts?

@ThisaruGuruge
Copy link
Member

@DimuthuMadushan If we can have an API in the GraphQL compiler plugin that returns a schema string that can be directly written to a file, and if there's a way to access that API from the graphql tool, I think we can resolve this.

The configurable variable approach looks good. If the consistency across the different tools isn't much of a concern, I'd prefer that option. @shafreenAnfar any thoughts?

@DimuthuMadushan
Copy link
Author

As discussed offline, due to the following reasons, decided to remove the schema file generation configs and generate the file always.

  1. The generated file will be used to transfer the schema to runtime. due to that, the file should be generated always.
  2. Moving the schema file generation logic to the CLI side will be complex in terms of handling dependencies. This also affects the above reason as well.
  3. Even though it's complex to add a CLI command, it also can be introduced without any API changes in the future.

The proposal is updated according to the changes.

@DimuthuMadushan DimuthuMadushan removed the Status/Active Proposals that are under review label Oct 6, 2022
@DimuthuMadushan DimuthuMadushan added the Status/Implemented Implemented proposals label Oct 6, 2022
@DimuthuMadushan DimuthuMadushan added Status/Draft In circulation by the author for initial review and consensus-building and removed Status/Implemented Implemented proposals labels Oct 7, 2022
@DimuthuMadushan DimuthuMadushan added Status/Active Proposals that are under review and removed Status/Draft In circulation by the author for initial review and consensus-building labels Oct 20, 2022
@DimuthuMadushan
Copy link
Author

To be consistent with the other implementation(e.g., openApi), the GraphQL schema file generation is moved to the CLI side. The proposal is updated with the new changes.

@ThisaruGuruge
Copy link
Member

To clarify the behavior. Once we completely implement this, to write the GraphQL schema to a file, we have two options:

  • Using the graphql tool (By providing the ballerina source file as an input)
  • Using the bal build command (By providing an additional build flag)

If this is the case, what was the reason behind having two different approaches?

If this is how OpenAPI tool handles the OpenAPI spec generation, what was the reason behind the decision?

@lnash94 thoughts?

@lnash94
Copy link
Member

lnash94 commented Nov 14, 2022

@ThisaruGuruge yeah we added the flag with the requirements.

  • In openAPI tool , OpenAPI CLI is the normal behaviour of the openAPI spec generation.

  • Later we added the --export-openapi flag to the bal build command to simplify the CLI usage according to the choreo requirements. What they required is to generate openapi specifications for all http services in the ballerina package. At that time, it is difficult to run multiple times openapi CLI for every ballerina http service.
    As a solution, we provide a flag for the build command. This flag has a compiler plugin implementation. Therefore this compiler plugin hits and executes code generation when it is an http service without involving OpenAPI CLI command.

@DimuthuMadushan DimuthuMadushan added Status/Accepted Accepted proposals and removed Status/Active Proposals that are under review labels Dec 8, 2022
@DimuthuMadushan DimuthuMadushan moved this from Prioritized to Done in Ballerina Team Main Board Jan 13, 2023
@DimuthuMadushan DimuthuMadushan added the Status/Implemented Implemented proposals label Jan 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module/graphql Issues related to Ballerina GraphQL module Points/1 Status/Accepted Accepted proposals Status/Implemented Implemented proposals Team/PCM Protocol connector packages related issues Type/NewFeature Type/Proposal
Projects
Archived in project
Development

No branches or pull requests

4 participants