Skip to main content

Postgraphile

The Mosaic framework uses GraphQL as the interface between the backend and the frontend workflows. The backends use PostGraphile to generate their GraphQL APIs. PostGraphile introspects the PostgreSQL database (tables, columns, relationships, etc.) to create a lightning-fast GraphQL API with powerful graph capabilities and filters.

GraphQL Setup and Configuration

PostGraphile offers an HTTP endpoint for GraphQL queries and mutations as well as a WebSocket endpoint to support GraphQL subscriptions. The setup adds these endpoints to the WebSocket-enabled HTTP server. The GraphQL endpoint is available at the route /graphql. The interactive GraphiQL IDE is added as /graphiql endpoint that allows you to conveniently view your GraphQL schema and execute queries and mutations. This endpoint can be disabled, e.g. for production deployments.

In general, you can tweak every aspect of the GraphQL API generation. The Mosaic framework provides a PostGraphile options builder which contains already reasonable defaults that you can further extend. The options define which plug-ins should be loaded (and in which order), settings on how the GraphQL API should be built, PostgreSQL settings for database queries, parses the HTTP request (e.g. for JWT parsing), etc.

We suggest enabling the following open-source PostGraphile plug-ins:

  • PgSimplifyInflectorPlugin - for nicer endpoint names.
  • ConnectionFilterPlugin - adds a powerful suite of filtering capabilities to a PostGraphile schema. This enables complex queries with single or multiple combined filter operations, different operators, string filters, and/or/not, etc. The drawback is that this can lead to expensive database operations. For internal/protected services, this is likely fine. However, for public/anonymous queries, special protection (like query pinning) is suggested.
  • AtomicMutationsPlugin - enables mutation atomicity with GraphQL requests containing multiple mutations.

and the following Mosaic-specific plug-ins:

  • SubscriptionsPluginFactory - a factory to create subscription plug-ins for your entities.
  • AxGuardPlugin - wraps resolver executions into an authentication check, making sure that that JWT subject is authorized to access the GraphQL resource.
  • EnforceStrictPermissionsPlugin - omits all GraphQL endpoints that don’t have any permission definition for it.
  • ValidationDirectivesPlugin - automatically adds validation notes to the comments of the GraphQL schema based on the database constraints.
  • AnnotateTypesWithPermissionsPlugin - automatically adds the permissions that allow to call the GraphQL endpoint to the schema description.

General Schema Generation

Based on your database tables, columns, and relationships, PostGraphile automatically creates the GraphQL query and mutation endpoints. For example, if you have a movies table that has a 1:n relation to a table movies_casts, it creates the following query endpoints (when using the default Mosaic settings - this can be fine-tuned):

  • movie - to get a movie by the unique ID.
  • movieByExternalId - to get a movie by another unique property (the ExternalId in this example).
  • movies - to query for movies with powerful filters, sorting, paging, cursors, and more.
  • moviesCast - to get the details of a single cast entry.
  • moviesCasts - to query for all casts in all movies with powerful filters, sorting, paging, cursors, and more.

The GraphQL API allows one to easily traverse the graph. From the movie entity, you can access the cast members that are part of the movie. This connection has again all the filters, sorting, paging, and other functionality to return exactly the data that the frontend needs.

To manipulate the data, PostGraphile generates (by default) the following mutation endpoints:

  • createMovie - create a new movie by providing values for at least the non-nullable fields.
  • createMoviesCast - create a movie cast entry related to a movie.
  • updateMovie - update an existing movie by providing the new values and the unique ID of the movie.
  • updateMovieByExternalId - same as the above but provides the unique external ID.
  • updateMoviesCast - update an existing movie cast entry.
  • deleteMovie - delete a movie by providing the unique ID.
  • deleteMovieByExternalId - delete a movie by providing another unique property (the ExternalId in this example).
  • deleteMoviesCast - delete a cast member entry for a movie.

In addition to the query and mutation endpoints, there is the GraphQL subscription endpoint. If the database is set up to issue change triggers, those are forwarded to the GraphQL subscribers. The endpoint name for all the movie and movie cast-related changes would be movieMutated.

A direct mapping from database tables (and their relations) to GraphQL API endpoints is likely how you will manage most of your GraphQL schema. Please see the Database / Schemas to find out the best practices to manage your database schema.

Developing GraphQL Plug-ins

PostGraphile generates the GraphQL API based on your PostgreSQL database already in a very useable way. Plugins allow you to further tweak and customize the aspects of how exactly the API should be generated.

The simplest way is to use the PostGraphile makeExtendSchemaPlugin. This allows you to adjust the GraphQL schema, for example, by providing a new query or mutation endpoint and adding corresponding resolvers to it.

Another option is to wrap existing resolvers and add your own logic before or after the resolver is called by utilizing the makeWrapResolversPlugin.

The most powerful, but also a more complex way, to fine-tune every aspect of the generated GraphQL API is to use the hooks. This lets you tweak the fields of GraphQL types, query and mutation operations, adjust input types, and much more.