Skip to content

Actions

As mentioned in the Schema section, actions are functions that can be invoked on a graph node. There we gave the example of a PullRequest type in membrane/github with a merge action.

Conceptually, of field queries map to reads, action invocations map to writes (or producing a side effect). You could think of fields like GET requests and actions like POST|PUT|DELETE.

Invoking actions

Invoking programmatically

Picking up from our Queries section, we’ll assume we have a program with a connection to the Membrane GitHub user like so:

NameGref
usergithub:users.one(name:'membrane-io')

Let’s query the repo for this docs site, find the latest pull request, and YOLO-merge it. Refer to docs on querying collections for a refresher on pagination in Membrane.

import {
const nodes: {
readonly user: github.User;
readonly clock: Clock;
readonly process: Process;
}

Contains the graph references (grefs) that this program has been given access to.

nodes
} from "membrane"
export async function
function example(): Promise<void>
example
() {
const
const prs: github.handles.PullRequestCollection & (() => github.handles.PullRequestCollection)
prs
=
const nodes: {
readonly user: github.User;
readonly clock: Clock;
readonly process: Process;
}

Contains the graph references (grefs) that this program has been given access to.

nodes
.
user: github.handles.User
user
.
github.handles.User.repos: github.handles.RepositoryCollection & (() => github.handles.RepositoryCollection)

Collection of Github repositories owned by the user

repos
.
github.handles.RepositoryCollection.one: (args: {
name: string;
}) => github.handles.Repository

Retrieve a single repository by name

one
({
name: string
name
: "docs" }).
github.handles.Repository.pull_requests: github.handles.PullRequestCollection & (() => github.handles.PullRequestCollection)

Collection of pull requests in the repository

pull_requests
const
const page: github.values.PullRequest[]
page
= await
const prs: github.handles.PullRequestCollection & (() => github.handles.PullRequestCollection)
prs
.
github.handles.PullRequestCollection.page: (args?: {
state?: string;
head?: string;
base?: string;
sort?: string;
order?: string;
page?: number;
pageSize?: number;
}) => github.handles.PullRequestPage

Retrieve a page of pull requests

page
().
github.handles.PullRequestPage.items: ListField<github.values.PullRequest> & (() => ListField<github.values.PullRequest>)
items
.
ListField<github.values.PullRequest>.$query: (q: string) => Promise<github.values.PullRequest[]>

Queries the graph starting at node referenced by this g-ref.

@paramquery The query to perform. Must be valid GraphQL query

@returnsThe result of the query. An object with the same shape as the query

@example

This example queries the status and body of the membrane.io website:

const { status, body } = await nodes.http.get({ url: "https://example.com" }).$query("{ status body }")

$query
("number title")
const {
const number: number | undefined
number
,
const title: string | undefined
title
} =
const page: github.values.PullRequest[]
page
[0]
if (
const number: number | undefined
number
) {
const
const latest: github.handles.PullRequest
latest
= await
const prs: github.handles.PullRequestCollection & (() => github.handles.PullRequestCollection)
prs
.
github.handles.PullRequestCollection.one: (args: {
number: number;
}) => github.handles.PullRequest

Retrieve a single pull request

one
({
number: number
number
})
const latest: github.handles.PullRequest
latest
.
github.handles.PullRequest.merge: (args?: {
commit_title?: string;
commit_message?: string;
sha?: string;
merge_method?: string;
}) => Action<void>
merge
({
commit_title?: string
commit_title
: `YOLO-merging ${
const title: string | undefined
title
}` }).
Action<void>.$invoke(): Promise<void>

Invoke this action

$invoke
()
// Instead of chaining `.$invoke()`, we could also simply await to invoke
await
const latest: github.handles.PullRequest
latest
.
github.handles.PullRequest.merge: (args?: {
commit_title?: string;
commit_message?: string;
sha?: string;
merge_method?: string;
}) => Action<void>
merge
({
commit_title?: string
commit_title
: `YOLO-merging ${
const title: string | undefined
title
}` })
}
}

In this example, we have a reference to a PullRequest node, which means we can invoke merge or other PR actions, like createComment. Note that since actions are graph nodes too, they can be assigned to variables and referenced just like fields.

To see all the different ways to invoke actions in your code, including via timers, read our actions API reference.

Invoking manually

You can also invoke actions manually, in the IDE sidebar and the dashboard. Here I’m invoking the createComment action on the PR that I’m currently working on:

Invoking from the CLI

Actions can also be invoked from the command line with our mctl CLI.

Terminal window
$ mctl action 'github:users.one(name:"membrane-io").repos.one(name:"docs").pull_requests.one(number:76).merge'

Defining actions

For each action declared in a program’s schema, you must define a corresponding function that gets called when the action is invoked.

On root

For example, when you create a new program using our blank template, we include a run action on its root node. To implement that action, we export a function from the top-level of the program’s index.ts entry file, or export a Root object with a method.

export async function
function run(): Promise<void>
run
() {
// Do something
}
export const
const Root: {
run: () => Promise<void>;
}
Root
= {
run: () => Promise<void>
run
: async () => {
// This also works
},
}

On nodes

And what about actions on graph nodes more deeply nested in a program’s schema? Let’s return to the pull request example.

The membrane/github defines a PullRequest type with a merge action in its schema. To implement the merge action, the driver exports a PR object with a merge method:

export const
const PullRequest: {
merge(): Promise<void>;
}
PullRequest
= {
async
function merge(): Promise<void>
merge
() {
// Call the GitHub API to merge the PR
},
}

Refer back to the Schema section for more detail on that PullRequest type, and view the membrane/github driver to see the source code (index.ts).