ENbext.dev
DocumentationExtensions

Traduction automatique depuis l’anglais. Consulter l’original.

Sur cette page

Construire un plugin

Ce guide vous guide dans la création d'un plugin bext à partir de zéro. Nous allons construire un plugin middleware "mode maintenance" qui renvoie une page 503 lorsqu'un indicateur est défini, en utilisant le bac à sable QuickJS.

Échafauder le projet#

bash
bext plugin init maintenance-mode
cd maintenance-mode

Cela crée la structure suivante :

code
maintenance-mode/
  plugin.toml        # Plugin manifest
  src/
    index.js         # Plugin entry point
  test/
    plugin.test.js   # Test harness

Le manifeste : plugin.toml#

Chaque plugin nécessite un plugin.toml qui déclare son identité et ses capacités :

toml
[manifest]
name = "maintenance-mode"
version = "0.1.0"
description = "Return a 503 maintenance page when enabled via config"
capabilities = ["middleware"]

[sandbox]
type = "quickjs"
max_memory_mb = 16
max_time_secs = 5
storage_quota_kb = 256

[permissions]
allowed_urls = []
max_fetch_per_minute = 0

Champs :

  • manifest.name — identifiant unique, en minuscules avec tirets.
  • manifest.capabilities — un ou plusieurs des éléments suivants : middleware, transform, lifecycle, cache_backend.
  • sandbox.type — quickjs, wasm ou nsjail.
  • sandbox.max_memory_mb — limite de mémoire pour le bac à sable (par défaut : 64 Mo).
  • sandbox.max_time_secs — délai d'expiration de l'horloge murale par appel de crochet (par défaut : 10 s).
  • permissions.allowed_urls — modèles globaux pour HTTP sortant. Vide signifie aucun accès HTTP.

Fonctions de crochet d’écriture#

Ouvrez src/index.js. Le plugin exporte les fonctions de hook de cycle de vie :

javascript
// src/index.js

// Called once when the server starts
export function onServerStart(config) {
  bext.storage.set("enabled", config.enabled ? "true" : "false");
  console.log(`Maintenance mode: ${config.enabled ? "ON" : "OFF"}`);
}

// Called on every incoming request (middleware capability)
export function onRequest(ctx) {
  const enabled = bext.storage.get("enabled");
  if (enabled !== "true") {
    return { action: "continue" };
  }

  // Allow health checks through
  if (ctx.path === "/healthz" || ctx.path === "/readyz") {
    return { action: "continue" };
  }

  return {
    action: "respond",
    status: 503,
    headers: [
      ["Content-Type", "text/html"],
      ["Retry-After", "300"],
    ],
    body: `<!DOCTYPE html>
<html><head><title>Maintenance</title></head>
<body><h1>We'll be back shortly</h1>
<p>Scheduled maintenance in progress.</p>
</body></html>`,
  };
}

// Called after the response is sent (async, non-blocking)
export function onRequestComplete(event) {
  if (event.status === 503) {
    bext.metric("maintenance_blocked", 1, [
      ["path", event.path],
    ]);
  }
}

// Called during graceful shutdown
export function cleanup() {
  console.log("Maintenance mode plugin shutting down");
}

API disponibles#

Dans le sandbox QuickJS, votre plugin a accès à :

API Description
bext.storage.get(key) Lire à partir du magasin KV limité à chaque plugin
bext.storage.set(key, value) Écrire dans le magasin KV (quota appliqué)
bext.storage.delete(key) Supprimer une entrée KV
bext.fetch(url, options) Client HTTP à débit limité et liste autorisée d'URL
bext.config Objet de configuration du plugin en lecture seule
bext.metric(name, value, tags) Émettre une métrique au pipeline d'observabilité
console.log/warn/error/info/debug Journalisation structurée

Configuration du plugin#

Dans le bext.config.toml de votre application, ajoutez la section plugin :

toml
[plugins.maintenance-mode]
sandbox = "quickjs"
path = "./plugins/maintenance-mode/src/index.js"

[plugins.maintenance-mode.config]
enabled = false

Tester localement#

Utilisez le programme d'exécution de test du plugin intégré :

bash
bext plugin test

Cela charge votre plugin dans un contexte QuickJS isolé et exécute les tests dans test/plugin.test.js :

javascript
// test/plugin.test.js
import { describe, it, expect } from "bext:test";

describe("maintenance-mode", () => {
  it("returns 503 when enabled", () => {
    plugin.call("onServerStart", { enabled: true });
    const result = plugin.call("onRequest", {
      path: "/dashboard",
      method: "GET",
    });
    expect(result.action).toBe("respond");
    expect(result.status).toBe(503);
  });

  it("passes through when disabled", () => {
    plugin.call("onServerStart", { enabled: false });
    const result = plugin.call("onRequest", {
      path: "/dashboard",
      method: "GET",
    });
    expect(result.action).toBe("continue");
  });

  it("always allows health checks", () => {
    plugin.call("onServerStart", { enabled: true });
    const result = plugin.call("onRequest", {
      path: "/healthz",
      method: "GET",
    });
    expect(result.action).toBe("continue");
  });
});

Débogage#

Activez la journalisation détaillée du plug-in avec la variable d'environnement BEXT_PLUGIN_LOG :

bash
BEXT_PLUGIN_LOG=debug bext dev

Ceci imprime toutes les sorties console.* de votre plugin, ainsi que l'utilisation des ressources du bac à sable (mémoire, nombre de récupérations, octets de stockage).

Pour inspecter le contenu du magasin KV au moment de l'exécution :

bash
bext plugin storage list maintenance-mode
bext plugin storage get maintenance-mode enabled
Conseil

Un permissions.allowed_urls = [] vide signifie que le plugin n'a aucun accès HTTP sortant. Ajoutez un modèle global pour activer les appels bext.fetch, ou laissez-le vide pour les plugins qui lisent uniquement bext.storage ou émettent des métriques.

Prochaines étapes#

  • Plugins QuickJS — référence API complète pour le bac à sable JS
  • Plugins WASM — créez des plugins hautes performances dans Rust
  • Édition — partagez votre plugin sur les plugins. bext.dev
Modifier cette page ↗Besoin d’aide ? ↗
Rechercher dans la documentation

Saisissez un sujet, une commande ou une question.