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] Decoupling GraphQL API development from API design #4620

Open
shafreenAnfar opened this issue Jun 27, 2023 · 3 comments
Open

[Proposal] Decoupling GraphQL API development from API design #4620

shafreenAnfar opened this issue Jun 27, 2023 · 3 comments
Labels
module/graphql Issues related to Ballerina GraphQL module Status/Active Proposals that are under review Team/PCM Protocol connector packages related issues Type/Proposal

Comments

@shafreenAnfar
Copy link
Contributor

shafreenAnfar commented Jun 27, 2023

Summary

When developing APIs there are two standard practises: code first and contract first. In the case of contract first you first design the GraphQL schema and then implement the agreed schema. This proposal is to improve Ballerina for contract first approach.

Goals

  • Improve contract first approach experience in Ballerina

Motivation

As mentioned in the summary API development can be broken into two main practises: code first and contract first. In the case of contract first, the schema design is done first and then the implementation is done second. This allows the schema to have its own evolution life-cycle and code to have its own. During schema design domain expert may play a significant role whereas during implementation technology expert may play a significant role. The time taken to design a particular schema and the time taken to implement a designed schema could also vary. Therefore, it makes sense to provide a way to independently evolve each of these.

Description

At the moment, Ballerina has a visualiser which allows us to design the schema. However the problem with the current implementation is we generate a service skeleton. This binds the design and development together.

Screenshot 2023-06-27 at 11 36 36

Instead of generating the service skeleton it is possible to generate service types. Following is an sample code.

import ballerina/graphql;

type snowtooth service object {
    *graphql:Service;

    resource function get allLifts(Status? status) returns Lift[];
}; 

public type Lift service object {
    *graphql:NestetedService;

    isolated resource function get id () returns string;
    isolated resource function get name () returns string;
    isolated resource function get status () returns string;
    isolated resource function get capacity () returns int;
    isolated resource function get night () returns boolean;
    isolated resource function get elevationgain () returns int;
    isolated resource function get trailAccess () returns Trail[];
};

public type Trail service object {
    *graphql:NestetedService;

    isolated resource function get id ();
    isolated resource function get name () returns string;
    isolated resource function get status () returns string;
    isolated resource function get difficulty () returns string?;
    isolated resource function get groomed () returns boolean;
    isolated resource function get trees () returns boolean;
    isolated resource function get night () returns boolean;
    isolated resource function get accessByLifts () returns Lift[];
};

public enum Status {
    OPEN,
    CLOSED,
    HOLD
}

This part of the code can be in a separate Ballerina package and can be released independently. Then the implementation code can add the dependency to the release package and continue implementing the schema.

service foo:snowtooth /graphql on new graphql:Listener(9090) {
}

In addition, the above code is enough to generate the GraphQL schema from the code. Effectively, this becomes an alternate syntax to define GraphQL schema.

However, the above to work, it is needed to introduce a new service type as graphql:NestetedService. Ballerina GraphQL module by default map service object types to GraphQL interfaces. Therefore, to distinguish GraphQL interfaces from GraphQL nested services, the proposed service type is needed.

Please note that, it is not going to be a breaking change.

Dependencies

  • Tooling needs to be improved to provide code suggestion as needed when the service type is explicitly mentioned
  • Update the GraphQL CLI tool
  • Update the VSCode visualiser
@shafreenAnfar shafreenAnfar added Type/Proposal module/graphql Issues related to Ballerina GraphQL module labels Jun 27, 2023
@shafreenAnfar
Copy link
Contributor Author

shafreenAnfar commented Jun 27, 2023

@hevayo @ThisaruGuruge @sachiniSam @sameerajayasoma

@sanjiva
Copy link

sanjiva commented Jun 27, 2023

We have discussed doing this same thing for HTTP services as well.

@ThisaruGuruge
Copy link
Member

I am +1 for this.

One concern is the name NestedService, which I think does not convey the proper message, we can come up with an alternative. Maybe graphql:Object? The idea is that when the user sees the code, it is clearly visible that it is a GraphQL object. This might not be aligned with the Ballerina terminology, but graphql:Object reads perfectly in this scenario.

@ThisaruGuruge ThisaruGuruge added Status/Active Proposals that are under review Team/PCM Protocol connector packages related issues labels Jun 28, 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 Status/Active Proposals that are under review Team/PCM Protocol connector packages related issues Type/Proposal
Projects
None yet
Development

No branches or pull requests

3 participants