Skip to content
View logicboard's full-sized avatar
Block or Report

Block or report logicboard

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Please don't include any personal information such as legal names or email addresses. Maximum 100 characters, markdown supported. This note will be visible to only you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
logicboard/README.md

Logicboard - Code Execution and REPL over WebSockets

Logicboard lets you run a blob of code or start REPL via WebSockets. A typical use case is an in-browser code editor which can run code in multiple languages.

How does it work?

The diagram below shows the overall architecture. Logicboard internally runs your code/REPL in a separate docker container and interacts with it via a pseudoterminal.

When running REPL, you can simply send a stdin via websocket and receive the stdout in response.

logicboard flow diagram

Demo

demo

This project consists of two parts:

  • Frontend: A web app with code editor, built in React
  • Backend: A websocket server that executes code, built in Elixir + Phoenix

Running Locally

We prefer asdf to manage runtime versions, please take a look at our .tool-versions for supported versions.

Else, please make sure the following languages are installed:

erlang 26.0
elixir 1.14.5
nodejs 16.13.2
yarn 1.22.19

You also need to install docker to generate language-specific images.

Setup

Please make sure docker is running, then run:

mix setup

This will:

  • Build Docker images for each language
  • Fetch project dependencies

Start the webapp and websocket server

  • Run mix phx.server
  • Visit http://localhost:4000 to launch the code editor
  • A WebSocket server will also be started at: ws://localhost:4000/socket/websocket

Websocket API

Logicboard provides an API to run code via websocket messages (aka Commands)

When connecting to the websocket server, you need to pass a Session ID, eg:

ws://localhost:4000/socket/websocket?session_id=abcd

Once the connection is established, you can start sending commands to run code or start REPL.

The run command

When you ask logicboard to run code, it also needs a few other things:

  • language: The programming language to use.
  • files: A list of files with the code to execute.

The files parameter is used to create a directory structure for your code, think of it as cloning your repository.

  • main (bool): Indicates this is the main file to run.
  • name (string): Name of the file/directory.
  • directory (bool): Whether the file is a directory.
  • content (string or array): For a regular file, this contains the text content of the file. In case of directories, it will contain other files/directories as children.

Consider the run command below, this will execute the contents of file main.py and return the result Hello, world! via stdout

run

{
	"event": "run",
	"payload": {
		"language": "python_3",
		"files": [{
			"main": true,
			"name": "main.py",
			"directory": false,
			"content": "print('Hello, world!')"
		}]
	}
}

repl

Starts an interactive REPL session

{
	"event": "repl",
	"payload": {
		"language": "python",
		"files": [{
			"main": true,
			"name": "main.py",
			"directory": false,
			"content": "<base 64 encoded>"
		}]
	}
}

stdin

Sends a stdin input to the repl session

{
	"event": "stdin",
	"payload": {
		"body": "help()"
	}
}

stdout

Output from repl session or, result of a run command

{
	"event": "stdout",
	"payload": {
		"body": "help()"
	}
}

kill

Stops current execution, or a repl session

{
	"event": "kill"
}

stop

Sent by the server when an execution/repl is stopped

{
	"event": "stop"
}

Can I add more languages?

Of course you can! Logicboard just needs:

  1. A Docker image to run
  2. Command to compile your code
  3. Command to start REPL (optional)

1. Create a dockerfile

Create a <lang name>.dockerfile inside containers

Make sure your docker image has bash installed during build step.

We also need a user app with home directory /home/app

2. Update languages.ts

The languages.ts file used by the web app to display a list of lanugaues

Update the languages.ts with a few details:

  • name: Name of your language
  • version: Language version
  • code: Language code - an identifier for your language
  • repel: A boolean to indicate whether your language supports REPL
  • example: A sample code that will be populated in the editor when your language is selected
  • main_file: Name of your main file
  • message: A placeholder message that will be displayed in the output area when your language is slected

3. Create your <language>.ex module

The <language>.ex module in languages directory is used by the bakend for code execution. We'll need the following:

  • name: The name of your language
  • version Language version
  • container_image: Ths function should return the image tag for your container. Use <your docker file name>:executor
  • run_command: The command used to execute code in your main file
  • repl_command: The command used to start REPL shell (or nil)

Once done, you also need to update the languages.ex module:

  • Add your language module to alias
  • Add entry to the @modules map, where the code is the language code you specified in section #2 above

Security Considerations

Containers are not a sandbox, and aren't safe for running arbitrary code, so please be careful!

Popular repositories

  1. logicboard logicboard Public

    Elixir 41 2