Skip to main content
Version: v0.14.1

Introduction

The Magellan project provides compiler tooling and a runtime API for remote execution of service functions written in TypeScript.

In many applications, backend developers have to create REST APIs, e.g., using swagger.io and frontend developers implement client code in their components to present domain logic and data in the browser. During development, frontend and backend developers usually have numerous discussions about this API, followed by changes and extensions on both sides. Magellan simplifies this process by providing a compiler that generates all involved code for both sides. It abstracts away the transport layer between the browser and the server and automatically serializes input and output values.

Magellan is a TypeScript library that provides a compiler and runtime API for service functions with the following features:

  • Transparent support to write services that consume node modules in the frontend
  • npm package generation of TypeScript server code for remote execution through node
  • (Almost) invisible transport layer between browser and server.
  • Effortless configuration of service endpoints
  • Automatic serialization of input/output values
  • Transparent error messages and exception handling

Prerequisites

Before you can use Magellan, you need to install the dependencies. You'll need a working Node environment with Node 18+, npm and npx (or yarn 1.22.0+)

npm -v  # v8
npx -v # v8
node -v # v18

Getting Started

In this interactive tutorial, we'll implement a small frontend application with a service that returns a greeting and a React component that displays it in the browser. This service will automatically be extracted from the frontend code and be executed on the server.

Create a new @quatico/magellan-starter project

  1. Run one of the following commands to create a new project.

With pnpm:

pnpm
pnpm create @quatico/magellan-starter

With npm:

npm
npm init @quatico/magellan-starter
  1. Follow the instructions in the terminal to complete the setup.
cd <name-of-your-project>

# install dependencies
pnpm install

# start the project
pnpm start

The react app at http://localhost:3030 presents us with greetings by the service running on the server. You can see this from the processor architecture in the greeting message (see screenshot below).

browser executed function

You can also verify this by looking at the network tab in the browser's developer tools where you'll see the calls made to the server for executing the greetMe function:

dev tools

How does it work?

Have a look at the src/services folder to see the example function that returns a greeting src/services/greet-me.ts. The function is annotated with the @service() decorator which marks it as a service function. Magellan will automatically extract this function and generate the corresponding server code.

src/services/greet-me.ts
import { type Context } from "@quatico/magellan-shared";
import { type Serialization } from "@quatico/magellan-shared";

// @service()
export const greetMe = async (name: string, context?: Context, serialization?: Serialization): Promise<string> => {
// This code must be executed on the server. In the browser, accessing process.arch causes an error.
return `Hello ${name}! I'm Magellan running on "${
typeof window === "undefined" ? `${process.arch}" server` : "browser"
}!`;
};

To verify, that the function can also be run in the browser, we can run the react app without Magellan.

pnpm run start:frontend

The react app at http://localhost:3030 presents us with greetings by the service running in the browser

browser executed function

Where does the server run?

In this example, the server runs on a different port (3001) than the frontend. To tell the Magellan client code where the server is running, we need to set the endpoint in the setNamespace call in src/App.tsx. Have a look at the following code snippet:

src/App.tsx
import { useEffect, useState } from 'react';
import logo from './logo.svg';
import { greetMe } from "./services/greet-me";
import { setNamespace } from "@quatico/magellan-client"

import './App.scss';

// we need to tell the Magellan client code, that the server is on a different port than the frontend
setNamespace("default", { endpoint: "http://localhost:3001/api" });

function App() {
...
}

export default App;