Templated queries is a more secure way of accessing the GraphQL APIs of Space Cloud. 😇
Often we want to provide a simpler, customised and restricted REST/GraphQL API to the frontend while enjoying the full flexibility of the GraphQL API on the backend. This is where templated queries come into the picture.
Templated queries let you expose a customised GraphQL API on top of the auto-generated GraphQL APIs of Space Cloud.
In short it allows frontend developers to send a simple, domain-specific query like this:
query {
changeName (userId: $userId, name: $name) @profile {
status
error
}
}while Space Cloud executes the following query behind the scenes:
mutation {
update_users (where: { id: $userId }, set: { name: $name }) @postgres {
status
error
}
}Let’s continue the example described above to see how we can add a templated query to Space Cloud and use it.
For the sake of this example, we will be assuming certain things like the table and database names, operation we want to perform, etc. You can change them as per your use case.
Add a database to Space Cloud, if you haven’t already.
Head over to the Overview tab of the Database section and click on the Add button to add the users table:
type users {
id: ID! @primary
name: String!
email: String!
}Then head over to the Browse tab of the Database section and click on the Insert button to add the following user record:
{
"id": "1",
"name": "John",
"email"
}Now, it’s time to create a templated query.
Templated queries are nothing but a kind of a remote endpoint, pointing to the Space Cloud’s GraphQL API internally.
Head over to the GraphQL API section under Microservices in the Mission Control. Click on the Add button to add the following remote service:
Service name: profileURL: xyz (The value of the URL doesn’t matter in this use case).After adding the remote service, you will be directed to its endpoints page. Click on the Add button there to add the following endpoint:
Endpoint name: changeNameEndpoint type: Space CloudTemplate output format: YAMLGraphQL query template:mutation {
update_users (where: { id: $userId }, set: { name: $name }) @postgres {
status
error
}
}Response body template under the Advanced options:{{marshalJSON .args.data.update_users}}That’s it! We have added our templated query!
Wondering what is that response body template? 🤔. The auto-generated GraphQL API of
update_userswill respond with thestatusanderrorfields under thedata.update_userskey. SincechangeNameis a GraphQL API on top ofupdate_users, we will get thestatusanderrorfields under thedata.changeName.data.update_users. To avoid that, we are transforming the response body of ourchangeNameendpoint to a JSON body with only the contents of thedata.update_users. We have used Go templates to describe the transformed response body above. Check out the docs of transformations to learn more about it in detail.
Time to use our templated query now!
Head over to the API Explorer section of the Mission Control. Copy-paste the following query and variables:
query {
changeName (userId: $userId, name: $name) @profile {
status
error
}
}Variables:
{
"userId": "1",
"name": "Rock"
}Hit the play button, and you should be able to see the following result as expected:
{
"data": {
"changeName": {
"status": 200
}
}
}To confirm that everything worked as expected, you can run this query:
{
users @postgres {
id
name
}
}You should be able to see this response:
{
"data": {
"users": [
{
"id": "1",
"name": "Rock"
}
]
}
}Congrats!! 🥳 You just learned how to use templated GraphQL queries in Space Cloud.
If you noticed in the getting started section above, a templated query is nothing but a remote endpoint. You can secure it using the same way you secure remote services in Space Cloud.
Many times, we don’t want to expose the details of our backend structure on the frontend like the names of the table, fields, database, etc.
Instead, we want to expose a more customised and domain-driven API which is easier to consume on the frontend. That’s a major use case when you might want to use templated queries, as we also saw above in our example.
Space Cloud’s auto-generated GraphQL API is very powerful. From complex joins to batch operations, you have got it all.
However, in a big application, there are chances of frontend not sending optimised queries. What if the frontend utilises links instead of the join clause that performs optimised SQL queries? What if the frontend updates two tables in different mutation queries, which should have been updated via a single batch query?
With great power comes great responsibilities. However, sometimes we are more comfortable restricting this responsibility to our backend team.
Using templated queries, your backend team can guarantee that the frontend always consumes optimised queries.
Let’s say we have a users table with the id, username, email and date_of_birth fields. And we only want the user to set the email field while updating his profile.
It’s possible to restrict the user from updating the other fields like username, date_of_birth, etc. by configuring proper security rules. However, writing security rules for such use cases can become tedious and error-prone if we have a lot of fields. Also remember, that set is just one operation, there are other operations as well like unset, rename, etc. which you might want to prevent.
Instead of writing and maintaining the security rules for such use cases, it is often easy to write a templated query that performs a given operation under the hood.