Schema
A Membrane program’s graph is defined by its schema, autogenerated in <your-program>/memconfig.json
based on the schema you configure in the Navigator panel.
The schema is a set of types that represent nodes in the program’s graph. Nodes can be fields, actions, or events.
- Fields: queryable nodes and values
- Actions: invocable functions on a node
- Events: subscribable notifications
Root Type
Schemas must include a Root
type which defines the type of the program’s root
node. This node serves as the entry point into the program—all references are relative to the root node.
Nodes are referred to by the program’s name followed by a colon and then a path to the node from the Root
type. For example:
github:
refers to the root node of the github drivertwitter:
refers to the root node of the twitter drivergithub:users.one(name:"membrane-io")
refers to a GithubUser
github:users.one(name:"membrane-io").repos.one(name:"directory")
refers to aRepository
Fields
Fields are queryable nodes that hold values you can read. From the github driver:
github:status
is a field of typeString
via thestatus
field on theRoot
typegithub:users
is a field of typeUserCollection
via theusers
field on theRoot
typegithub:users.one(name:"membrane-io")
refers to a node of typeUser
github:users.one(name:"juancampa")
refers to another node of typeUser
The two last examples show that parameters can be passed to fields where each combination of parameters represent a different node in the graph.
We call these references handles or grefs (short for graph reference).
Actions
Actions are functions that can be invoked in the context of a graph node. Note that since actions are graph nodes too, they can be passed around and referenced just like fields.
Events
Any Membrane program can emit events and subscribe to events.
For example, if you have a program that handles GitHub webhooks, your program could emit a ghWebhookReceived
event, and another program that forwards GitHub notifications to Slack could subscribe to that event.
Emitting an event
import type { const root: Root
A gref to the root of this program.
root } from "membrane";
export const const endpoint: (req: {
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
path: string;
body?: string;
query?: string;
headers: string;
}) => string
endpoint: resolvers.interface resolvers.Root
Root["endpoint"] = (req: {
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
path: string;
body?: string;
query?: string;
headers: string;
}
req) => {
switch (`${req: {
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
path: string;
body?: string;
query?: string;
headers: string;
}
req.method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS"
method} ${req: {
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
path: string;
body?: string;
query?: string;
headers: string;
}
req.path: string
path}`) {
case "POST /gh-webhook-path":
const root: Root
A gref to the root of this program.
root.ghWebhookReceived.$emit();
/* ... */
}
};
Subscribing to an event
Programs can subscribe an action to handle an event. When an event is emitted, the action will be invoked with an additional parameter called event
.
import type { import nodes
nodes } from "membrane";
export async function function sendToSlack(_: any, { event }: {
event: any;
}): Promise<void>
sendToSlack(_: any
_, { event: any
event }) {
await import nodes
nodes.slack.channel(/* ... */).sendMessage(/* ... */);
}
export async function function configure(): Promise<void>
configure() {
import nodes
nodes.ghWebhookReceived.$subscribe(function sendToSlack(_: any, { event }: {
event: any;
}): Promise<void>
sendToSlack);
}