Plugin System - green-ecolution/backend GitHub Wiki

Why a Plugin System?

The way trees are managed and represented can vary significantly between different municipalities. Each municipality has its own requirements, data structures, and business rules, which may differ greatly from those of others. For example, Municipality A might store detailed information on tree species, soil composition, and maintenance history, whereas Municipality B may primarily focus on location data and permit processes.

To accommodate this diversity while maintaining a unified system foundation, we have introduced a flexible plugin system. This allows each municipality to tailor the software to its specific needs by developing custom extensions without modifying the core functionality. For instance, Municipality A can create a plugin that aligns perfectly with its data structure and administrative practices, while Municipality B can implement a completely different, yet equally seamless, integration. This modularity ensures that the system remains adaptable and future-proof while providing a robust and scalable foundation.

image

The backend provides an endpoint where plugins can dynamically register at runtime. This means that new plugins can be integrated into the system without requiring a restart or manual configuration. To successfully register a plugin, it must authenticate itself with a Client ID and a Client Secret. Once registered, the plugin gains access to backend functionalities and receives the following authentication tokens:

  • Access Token: Used to access protected resources and has a limited lifespan. With this access token, the plugin can send requests to the backend via the API interface. This allows the plugin to interact with backend services, retrieve necessary data, and perform authorized operations within the system. The token must be included in the request headers to authenticate each API call.

Additionally, each plugin registration includes:

  • Provider: A unique key identifying the plugin (e.g., a slug). The provider allows the system and the plugin to establish a clear ownership structure, ensuring that specific entities are managed by the appropriate plugin.
  • Additional Information: Arbitrary JSON data that can store extra metadata about the plugin. This field follows a key-value structure (map[string]any), enabling plugins to store various relevant details. For example, a plugin can track which entities it manages versus those stored in the main system, enhancing integration and data consistency.

Runtime Registration and Heartbeat Mechanism

Plugins can be dynamically registered at runtime. To ensure that a plugin remains active, the system employs a heartbeat mechanism.

  • Heartbeat Functionality: A registered plugin periodically (e.g., every minute) sends a heartbeat signal to the backend.
  • Deregistration: If a plugin fails to send a heartbeat signal within a defined interval, it is marked as inactive, automatically deregistered, and removed from the plugin list. Additionally, a plugin can proactively deregister itself by sending an unregister request to the backend, ensuring it is properly removed from the system.

Plugin Parameters

Parameter Description
Slug The part of the URL under which the plugin is accessible (e.g., /api/v1/plugin/[slug]).
Name The name of the plugin used for identification.
Version The version of the plugin to ensure compatibility.
Description A short description of the plugin and its functionality.
Plugin Host Path The host address of the plugin, e.g., https://plugin.xyz.com.

Reverse Proxy Integration

The backend uses an internal reverse proxy to transparently forward requests directed at plugins. This process works as follows:

  1. A plugin hosts its functionality at https://plugin.xyz.com.
  2. The backend is accessible at https://app.green-ecolution.de.
  3. When a request is sent to https://app.green-ecolution.de/api/v1/plugin/[slug] (where [slug] is the unique identifier of the plugin), the request is automatically forwarded to the plugin's host address (https://plugin.xyz.com).

Example

A plugin with the slug csv_import is hosted at https://csv.example.com. If a user sends a request to:

https://app.green-ecolution.de/api/v1/plugin/csv_import

... the backend internally redirects the request to:

https://csv.example.com

Creating a Plugin

Green Ecolution offers a flexible plugin system that allows developers to extend the platform's functionality while maintaining modularity and separation of concerns. This system enables seamless integration of custom logic, tailored data processing, and additional features specific to each municipality's requirements.

A plugin in Green Ecolution consists of two main components:

  1. Backend Implementation – Provides server-side functionality, including authentication, registration and communication with the core system. This can be done in any programming language. We will walk through the implementation using the Go programming language. The backend also provides published helper packages in Go for the basic logic of the plugin functionality, such as registering, deregistering and sending heartbeats.
  2. Frontend Integration (React) – Allows the integration of user interfaces and workflows via module federation. This has to be a React Component.

By following the guidelines below, developers can efficiently create and integrate plugins into the Green Ecolution ecosystem.

Server Implementation

Go Package

To streamline the development of backend plugins, Green Ecolution provides a dedicated Go package that simplifies the integration process. This package includes essential functionalities such as:

  • Automatic Registration – Plugins register themselves with the backend upon startup.
  • Heartbeat Mechanism – Ensures that the plugin remains active and available by sending regular heartbeat signals.
  • Authentication & Token Refresh – Handles secure authentication and automatic token renewal.
Installation

To install the official Green Ecolution plugin package, run the following command:

go get github.com/green-ecolution/green-ecolution-backend/pkg/plugin
Usage and Documentation

Comprehensive documentation, including API references and example implementations, is available at: GoDoc: Green Ecolution Plugin Package

[!NOTE]
In addition to the plugin package, Green Ecolution provides a client package for interacting with the system. See: GoDoc: Green Ecolution Client Package

Frontend Plugin (React)

Frontend plugins in Green Ecolution are built using React and integrated via Module Federation, allowing independent deployment and seamless interaction with the core application. Module Federation is a Webpack and Vite feature that allows separate applications (or plugins) to dynamically load and share modules at runtime. In the case of Green Ecolution, this mechanism enables frontend plugins to be loaded dynamically without requiring changes to the core application.

How it Works in Green Ecolution:

  • The main application (Green Ecolution frontend) acts as a host that dynamically loads external plugins.
  • Each plugin is a separate microfrontend (a remote) that exposes its components via Module Federation.
  • The host application fetches and integrates plugins on demand, ensuring modularity and flexibility.

Prerequisites

To develop a frontend plugin, ensure that the following dependencies are installed:

Dependencies:

  • "@green-ecolution/plugin-interface": "^0.0.1"

Dev Dependencies:

  • "@module-federation/vite": "^1.1.9"

Additionally, the React version of the plugin must match the main frontend version. The current required versions are:

  • "react": "^18.3.1"
  • "react-dom": "^18.3.1"

Example Vite Configuration

To integrate a plugin using Vite and Module Federation, use the following configuration:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { federation } from "@module-federation/vite";

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    react(),
    federation({
      name: "csv-import",          // use slug as name here
      filename: "plugin.js",       // use always plugin.js
      exposes: {
        "./app": "./src/App.tsx",  // use ./app
      },
      shared: ["react", "react-dom", "@green-ecolution/plugin-interface"],
    }),
  ],
  base: "",
  build: {
    target: "esnext",
  },
});

Deployment

Once the plugin is built, it can be deployed and dynamically loaded by the Green Ecolution frontend. The system will automatically detect and integrate registered plugins, ensuring a smooth and modular extension mechanism.