What is Membrane?

A fast, powerful way to write internal tools in TypeScript, connecting the apps you already use at work.

FEATURES
EXAMPLES
example github discord tracker
Send a Discord message when a commit is pushed to Github.
Save repository and channel information in state
Subscribe to event
Send message to Discord
import { nodes, root, state } from "membrane";

export async function configure({ discordUrl, repo }) {
  const [user, repository] = repo.split("/");

  state.discordUrl = discordUrl;
  state.repository = repository;
  state.user = user;

  await nodes.github.users
    .one({ name: user })
    .repos.one({ name: repository })
    .pushes.$subscribe(root.handlePushEvent);
}

export async function handlePushEvent(_, { event }) {
  const res = await event.commit.$query(
    `{ message, html_url, author { login } }`
  );

  const body = {
    username: "Github alert",
    content: `${res.author.login} pushed to
      ${state.user}/${state.repository}: -
      ${res.message} (${res.html_url})`,
  };

  await fetch(state.discordUrl, {
    method: "POST",
    body: JSON.stringify(body),
    headers: {
      "Content-Type": "application/json",
    },
  });
}
What is Membrane?

A fast, powerful way to write internal tools in TypeScript, connecting the apps you already use at work.

FEATURES
EXAMPLES
Send a Discord message when a commit is pushed to Github.
Save repository and channel information in state
Subscribe to event
Send message to Discord
import { nodes, root, state } from "membrane";

export async function configure({ discordUrl, repo }) {
  const [user, repository] = repo.split("/");

  state.discordUrl = discordUrl;
  state.repository = repository;
  state.user = user;

  await nodes.github.users
    .one({ name: user })
    .repos.one({ name: repository })
    .pushes.$subscribe(root.handlePushEvent);
}

export async function handlePushEvent(_, { event }) {
  const res = await event.commit.$query(
    `{ message, html_url, author { login } }`
  );

  const body = {
    username: "Github alert",
    content: `${res.author.login} pushed to
      ${state.user}/${state.repository}: -
      ${res.message} (${res.html_url})`,
  };

  await fetch(state.discordUrl, {
    method: "POST",
    body: JSON.stringify(body),
    headers: {
      "Content-Type": "application/json",
    },
  });
}
Communication

If you're curious about Membrane's architecture, Juan joined the devtools.fm podcast to talk through the nuts and bolts.



Enter your email for occasional updates