Skip to content

Latest commit

 

History

History
194 lines (122 loc) · 9.34 KB

005-graphql-api.md

File metadata and controls

194 lines (122 loc) · 9.34 KB

GraphQL API

Summary

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

GraphQL vs REST API

A REST API is an architectural concept for network-based software. GraphQL, on the other hand, is a query language, a specification, and a set of tools that operates over a single endpoint using HTTP. In addition, over the last few years, REST has been used to make new APIs, while the focus of GraphQL has been to optimize for performance and flexibility.

While Appwrite REST API is an easy way to get started with Appwrite quickly, GraphQL will allow better performance for specific use-cases and new ways to integrate Appwrite with platforms that we don't yet support that relies on that protocol. Ex: iOS, Android, or Gatsby.js.

The new Appwrite GraphQL API is not designed or aimed to replace the REST API, but rather to complete it and work well alongside it.

Problem Statement (Step 1)

What problem are you trying to solve?

While Appwrite REST API is easy and simple to use, a lot of developers would prefer to integrate their API and client applications using a GraphQL API. GraphQL can be a bit more complex but also more flexible and introduce better performance in some use-cases.

What is the context or background in which this problem exists?

Developers using Appwrite should not be forced to integrate with the server using a specific protocol. Appwrite should be protocol agnostic and provide multiple integrations API for different use-cases and ease of use for developers who come with particular perforations or existing knowledge.

Once the proposal is implemented, how will the system change?

We'll introduce a new API route called POST /v1/graphql. The new endpoint will parse, and route GraphQL requests to existing Appwrite controllers and routes and return the same response models as the Appwrite REST API endpoints.

Design proposal (Step 2)

Create a New Route

Create a new route called POST /v1/graphql. The new endpoint will initialize the GraphQL parser webonyx/graphql-php. We should use Utopia PHP routes object callbacks and metadata to init GraphQL queries and mutations.

Get Route by Method Name

Each Appwrite route has a label with its method name (->label('sdk.method', 'getPrefs')). This label was used only to generate the REST API SDKs using the SDK generator. We should preload all the routes and sort them in a hash where the method name is the key for fast routing between the different GraphQL API actions.

Query Example:

query accountGet { # [serviceName][ActionName]
  user { # Returned Model
    name
    email
  }
}

Mutation Example:

mutation usersCreate { # [ServiceName][ActionName]
  user { # Returned Model
    name
    email
  }
}

Load Routes, Models, and Collections

Load all Appwrite relevant routes, models, and Database collections into the GraphQL parser library. Any GET routes should be loaded as GraphQL queries, any POST, PUT, PATCH, or DELETE methods should be loaded as mutations. Both Appwrite Models objects and Database collections should be loaded as GraphQL objects. All the data is available using existing Appwrite libraries. Make sure to also include models for error objects (dev & non-dev).

Authentication

We need to make sure authentication is enforced in the context of each specific GraphQL action. An endpoint that can only be used with an API key or can only be accessed by an authenticated user should act exactly the same for the GraphQL API. Because the GraphQL endpoint is basically just another public HTTP endpoint as part of the Appwrite HTTP server, it can grant access to all the different server actions.

To avoid this situation, we need to enforce scopes based security with an additional layer that will be implemented inside the GraphQL controller.

Authentication Flow

This section handles the current socpes + roles based authentication: https://github.com/appwrite/appwrite/blob/f9afa2c95152b15eb079c1c65f249be4fe201c75/app/controllers/general.php#L164-L218

Error Handling

TODO. Available resources:

References:

Documentation

Create a new dedicated documentation page for using the GraphQL API. List all the different authentication methods, actions available, and response models.

Tests

To fully test the integration we would need to create a test suite for both Client and Server authentication methods similar to what we're doing in our REST API. We can use mghoneimy/php-graphql-client as a dev dependency for sending GraphQL API calls. Create some tests that are testing for system failure and authentication integritiy.

Tutorial

Create a short tutorial that explains how to use the new API in common use-cases.

Prior art

Public GraphQL APIs:

An Appwrite POC available on the graphql branch: https://github.com/appwrite/appwrite/compare/0.7.x...graphql?expand=1

Unresolved questions

We should find an alternative way to handle the custom JSON object that we currently use in the REST API. One example is the user prefs key-value object, which doesn't have a predefined structure. Another is the Function objects vars attribute that can hold a custom key-value object.

Future possibilities

The new API will allow integration with more GraphQL supported tools.