To query the Membrane graph, you need to specify two things:
When querying from the CLI you can use mctl query
:
$ mctl query --help
mctl query
Queries a program
USAGE:
mctl query <GREF> [QUERY]
ARGS:
<GREF> Node to query
<QUERY> Query to perform or empty if gref points to scalar
For example, the following command queries two fields from a Github user:
$ mctl query 'github:users.one(name:"membrane-io")' '{ avatar_url email }'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
| |
|---> Reference to a Github user |
|---> Selects fields from User
# Result:
{
"avatar_url": "https://avatars.githubusercontent.com/u/22850573?v=4",
"email": "juan@membrane.io"
}
Since the query uses GraphQL, you can select subfields too:
$ mctl query 'github:users.one(name:"membrane-io")' '{ email repos { one(name:"directory") { url } } }'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
subfields of the "repos" field <---|
# Result:
{
"email": "juan@membrane.io",
"repos": {
"one": {
"url": "https://api.github.com/repos/membrane-io/directory"
}
}
}
Sometimes you want to query a single scalar, the most concise way is to directly reference the scalar, that way you don't even need to pass a GraphQL query.
$ mctl query 'github:users.one(name:"membrane-io").email'
# Result:
juan@membrane.io
Programs can query nodes in its dependencies by await
ing a handle or using the $query
method. To give
access to the repository above, we can add it to memconfig.json:
{
"dependencies": {
"repo": "github:users.one(name:"vercel").repos.one(name:"next.js")"
}
...
}
Now nodes.repo
is available and points to the vercel/next.js repo
Reading a single scalar from the graph is pretty straight forward:
import { nodes } from "membrane";
// Scalars can be awated directly
const branch = await nodes.repo.default_branch;
console.log(`Default branch is "${branch}"`);
// Or use GraphQL syntax in $query. Outer braces can be omitted.
const res = await nodes.repo.$query(`full_name, stargazers_count`);
console.log(`Repo "${res.full_name}" has ${res.stargazers_count} stars`);
// Output:
// Default branch is "main"
// Repo "vercel/next.js" has 98304 stars
The main difference to vanilla GraphQL is that queries can be rooted at any node, whereas in regular GraphQL, all queries are rooted on the schema's "Query" type.
Membrane also has references as a primitive type. That way you can pass handles to other nodes and compose functionality easily.
These two differences are very powerful as you can pass handles around to specific parts of the graph without providing access to the entire graph.