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
: profile
URL
: 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
: changeName
Endpoint type
: Space Cloud
Template output format
: YAML
GraphQL 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_users
will respond with thestatus
anderror
fields under thedata.update_users
key. SincechangeName
is a GraphQL API on top ofupdate_users
, we will get thestatus
anderror
fields under thedata.changeName.data.update_users
. To avoid that, we are transforming the response body of ourchangeName
endpoint 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.