RaisFastRaisFast
Plugins

Overview

Extend RaisFast with plugins — JS, Lua, Rhai, or WASM. Write a working plugin in minutes.

Plugins are the extension mechanism for RaisFast. A plugin is a directory with a manifest.toml and an entry file. That's it.

Your First Plugin

raisfast plugin new my-plugin --runtime js

This generates:

extensions/plugins/my-plugin/
├── manifest.toml
└── main.js

Write your first hook handler in main.js:

import { logInfo } from 'sdk';

export function on_content_created(input) {
  const data = JSON.parse(input);
  logInfo("new content: " + data.id);
}

Start the server — the plugin loads automatically. Every time content is created, you'll see the log.

Architecture

manifest.toml          entry file (.js / .lua / .rhai / .wasm)
      │                         │
      └─────────┬───────────────┘

         PluginManager (Arc-shared)
           ├─ Topological sort (dependency order)
           ├─ JS / Lua: per-request (fresh VM each call)
           ├─ Rhai: per-request (pre-compiled AST, fresh Scope)
           ├─ WASM: instance pool (round-robin)
           └─ Hot-reload (filesystem watcher)


         Host API (sandboxed, permission-gated)
           ├─ Database (query / insert / update / delete)
           ├─ HTTP client (GET / POST)
           ├─ Virtual filesystem (read / write / list)
           ├─ KV store (per-plugin namespace)
           ├─ Config reader
           └─ Events, logging, ID generation

Four Runtimes

JavaScriptLuaRhaiWASM
EngineQuickJSmlua (Lua 5.4)Rhaiwasmtime
Entrymain.jsinit.luainit.rhaiplugin.wasm
SDK Importimport { ... } from 'sdk'local sdk = require("sdk")None (global scope)WIT interface
ConcurrencyPer-requestPer-requestPer-requestInstance pool
LanguageES2024 (async/await)Lua 5.4Rust-like DSLRust, Go, C, Zig
Best forQuick integrationsGame / embedded devsSimple automationHeavy computation

Three script runtimes can be compiled and loaded simultaneously. WASM is compiled separately via Cargo Feature flags.

JavaScript

import { dbQuery, ok, logInfo } from 'sdk';

export function on_content_created(input) {
  const data = JSON.parse(input);
  logInfo("created: " + data.id);
}

export function getProducts() {
  const rows = dbQuery("SELECT * FROM products");
  return ok(rows);
}
  • Runtime: QuickJS (ES2024, async/await, optional chaining)
  • Entry: main.js
  • Import SDK: import { ... } from 'sdk'

Lua

local sdk = require("sdk")
Plugin = {}

Plugin.on_content_created = function(input)
  local data = sdk.extractJson(input, "body")
  sdk.logInfo("created: " .. tostring(data.id))
end

Plugin.getProducts = function(input)
  local rows = sdk.dbQuery("SELECT * FROM products")
  return sdk.ok(rows)
end
  • Runtime: Lua 5.4 (sandboxed: no IO/OS/debug)
  • Entry: init.lua
  • Import SDK: local sdk = require("sdk")

Rhai

fn on_content_created(input) {
  log("info", "created: " + input.id);
}

fn get_products(input) {
  let rows = db_query("SELECT * FROM products", "");
  rows
}
  • Runtime: Rhai (Rust-native scripting, no SDK import needed)
  • Entry: init.rhai
  • Host functions injected directly into global scope

What Plugins Can Do

FeatureDescription
HooksReact to events — content created, user login, cron tick, etc.
RoutesServe custom REST API endpoints
CronSchedule background jobs with cron expressions
DatabaseQuery and mutate data (permission-gated)
HTTPMake outbound HTTP requests (whitelist-gated)
VFSPer-plugin sandboxed filesystem
KV StorePer-plugin key-value storage
EventsEmit and listen to custom events

Plugin Anatomy

my-plugin/
├── manifest.toml    ← metadata, permissions, hooks, routes, cron
└── main.js          ← entry file (.js / .lua / .rhai / .wasm)

Minimal manifest:

[plugin]
id = "com.example.my-plugin"
name = "My Plugin"
version = "0.1.0"
runtime = "js"
entry = "main.js"

Hot Reload

When PLUGIN_HOT_RELOAD=true (default), editing a plugin file reloads it automatically — no server restart needed. 1-second debounce, 2-second poll interval.

Management

# CLI
raisfast plugin check                    # Validate all plugins
raisfast plugin check ./plugins/my-plugin # Validate specific plugin

# Admin API
GET    /api/v1/admin/plugins              # List all plugins
GET    /api/v1/admin/plugins/{id}         # Plugin detail
POST   /api/v1/admin/plugins/{id}/reload  # Reload a plugin
POST   /api/v1/admin/plugins/{id}/disable # Disable
POST   /api/v1/admin/plugins/{id}/enable  # Enable
DELETE /api/v1/admin/plugins/{id}         # Uninstall

Next

On this page