Querying using mctllink

To query the Membrane graph, you need to specify two things:

  • The node you want to query, and
  • The data you want to retrieve, using GraphQL.

When querying from the CLI you can use mctl query:

$ mctl query --help
mctl query

Queries a program

    mctl query <GREF> [QUERY]

    <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"

Querying a single scalarlink

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:

Querying another programlink

Programs can query nodes in its dependencies by awaiting 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

Membrane's GraphQLlink

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.