GraphQL: Proxy Objects
Database objects don't normally provide a GraphQL-friendly interface. e.g. example::animal
provides underscore_names, but GraphQL consumers usually expect mixedCaseNames. Proxy objects may provide a different interface; they may also add additional methods.
Example
This is a modification of example-graphql.cpp
from Getting Started.
#include <btb/graphql.hpp>
#include <eosio/reflection2.hpp>
#include "example.hpp"
// GraphQL proxy for example::animal
struct Animal
{
// The proxy holds a copy of the original database object instead
// of holding a pointer or reference. This is necessary because
// the database object gets destroyed when the table object goes
// out of scope from within Query::animal(). A potential workaround
// is to make the table object a member of the contract object.
example::animal obj;
// These methods have no arguments, so act like fields in GraphQL
auto name() const { return obj.name; }
auto type() const { return obj.type; }
auto owner() const { return obj.owner; }
auto purchasePrice() const { return obj.purchase_price; }
// This method has an argument, so needs method(...) in the
// EOSIO_REFLECT2 definition below.
auto isA(eosio::name type) const { return type == obj.type; }
};
EOSIO_REFLECT2(Animal, name, type, owner, purchasePrice, method(isA, "type"))
struct Query
{
eosio::name contract;
// Returns a Proxy object instead of returning the original object
std::optional<Animal> animal(eosio::name name) const
{
example::animal_table table{contract, contract.value};
auto it = table.find(name.value);
if (it != table.end())
return Animal{*it};
else
return std::nullopt;
}
};
EOSIO_REFLECT2(Query, //
contract, // query a field
method(animal, "name") // query a method; identifies the argument names
)
void example::example_contract::graphql(const std::string& query)
{
Query root{get_self()};
eosio::print(btb::gql_query(root, query, ""));
}
void example::example_contract::graphqlschema()
{
eosio::print(btb::get_gql_schema<Query>());
}
Example Query
This query:
{
animal(name: "fido") {
name
type
owner
purchasePrice
isACat: isA(type: "cat")
isADog: isA(type: "dog")
}
}
Produces this result:
{
"data": {
"animal": {
"name": "fido",
"type": "dog",
"owner": "alice",
"purchasePrice": "100.0000 EOS",
"isACat": false,
"isADog": true
}
}
}