Plugins

This guide explains how to install, activate, deactivate, and delete plugins from the admin panel.

Accessing Plugin Management

Navigate to Plugins in the admin sidebar. The page lists all installed plugins with their status.

Required permission: Admin role for viewing, Super-admin for upload/activate/deactivate/delete.

Plugin List

The plugin list shows:

ColumnDescription
NamePlugin display name
VersionInstalled version
Provider TypeUnique identifier used for routes and settings
StatusActive or Inactive badge
FrontendWhether the plugin includes a frontend bundle
InstalledWhen the plugin was installed
HealthLast known health check result

Uploading a Plugin

  1. Click Upload Plugin and choose a .tgz file (max 50 MB).
  2. The server validates the archive: checks format, package.json metadata, path traversal, and size limit.
  3. On success, the plugin appears in the list as Inactive.

The plugin archive must contain a package.json with a pokerEnginePlugin field including providerType and displayName.

Activating a Plugin

Click Activate on an inactive plugin. The server:

  1. Dynamically imports the plugin entry point.
  2. Calls the plugin’s register() function.
  3. Sets the plugin to active in the database.

If activation fails (missing register() export, runtime error), an error message is shown.

Deactivating a Plugin

Click Deactivate on an active plugin. The server:

  1. Checks that no active payment systems depend on this plugin’s provider type.
  2. Removes all registered hooks, filters, and routes.
  3. Sets the plugin to inactive (settings are preserved).

If payment systems depend on the plugin, a 409 Conflict error is shown listing the dependent systems. Disable those payment systems first.

Upgrading a Plugin

The Plugins page has no upgrade control, so upgrade through the API below with the new .tgz file:

  1. Send the file to the upgrade endpoint.
  2. The server validates the archive (same checks as upload, plus providerType must match).
  3. The old version is deactivated, the new files are swapped in atomically, and the new version is registered.
  4. If the upgrade fails, the old version is automatically restored.
  5. Settings are preserved across upgrades.

Connected clients receive a plugin:updated WebSocket event and automatically reload the plugin’s frontend bundle.

API

POST /api/v1/admin/plugins/:id/upgrade — Super-admin. Multipart .tgz upload (same as install).

Deleting a Plugin

Click Delete on an inactive plugin. A confirmation dialog appears. Deletion:

  1. Removes the plugin files from disk.
  2. Deletes the database record (settings are cascade-deleted).

Active plugins cannot be deleted — deactivate first.

Plugin Settings

Plugins that declare configFields in their package metadata show a Settings (gear) button in the actions column. Click it to open the auto-generated settings form.

Supported Field Types

TypeControlNotes
textText inputDefault for unknown types
passwordPassword input with show/hide toggleEncrypted at rest
numberNumber inputValidated server-side
toggleOn/off switchStored as "true" / "false"
selectDropdownOptions defined in configFields
textareaMulti-line text area—

Settings Flow

  1. Navigate to Plugins → Settings for the plugin.
  2. Fill in the form. Required fields are marked with a red asterisk.
  3. Click Save. The server validates required fields and type constraints.
  4. Plugins can register custom validation via the plugin:settings:validate filter hook.
  5. Password-type values are encrypted before storage and decrypted on read.

Settings API

MethodPathPermissionDescription
GET/api/v1/admin/plugins/:providerType/settingsAdminGet settings + field definitions
PUT/api/v1/admin/plugins/:providerType/settingsSuper-adminSave settings
GET/api/v1/config/plugin-settings/:providerTypeAuthenticatedPublic settings (no passwords)

API Endpoints

MethodPathPermissionDescription
GET/api/v1/admin/pluginsAdminList all plugins
GET/api/v1/admin/plugins/:idAdminGet plugin details
POST/api/v1/admin/plugins/uploadSuper-adminUpload plugin .tgz
POST/api/v1/admin/plugins/:id/activateSuper-adminActivate plugin
POST/api/v1/admin/plugins/:id/deactivateSuper-adminDeactivate plugin
POST/api/v1/admin/plugins/:id/upgradeSuper-adminUpgrade plugin with new .tgz
DELETE/api/v1/admin/plugins/:idSuper-adminDelete inactive plugin
GET/api/v1/admin/plugins/:providerType/settingsAdminGet plugin settings
PUT/api/v1/admin/plugins/:providerType/settingsSuper-adminSave plugin settings
POST/api/v1/admin/plugins/:providerType/health-checkAdminTrigger on-demand health check

Plugin Health Checks

Plugins can declare hasHealthCheck: true in their package.json pokerEnginePlugin field and export a healthCheck(registry) function. The engine uses this to monitor plugin operational status.

How it works

  • On-demand check: Click the Check Health button (pulse icon) on the Plugins page for any active plugin that declares hasHealthCheck.
  • Periodic check: The engine automatically runs health checks every 5 minutes for all loaded plugins with a registered healthCheck export.
  • After activation: A health check runs automatically after a plugin is activated.
  • After settings saved: A health check runs automatically after plugin settings are updated.

Health status indicators

The Health column on the Plugins page shows a coloured dot:

Dot colourMeaning
GreyNo health data yet (never checked)
GreenLast check passed (healthy)
RedLast check failed (unhealthy)

Circuit breaker integration

An unhealthy health check result increments the plugin’s circuit breaker error counter by 10 points. If a plugin reports unhealthy status repeatedly and the counter reaches 50 within a 5-minute window, the circuit breaker triggers and the plugin is automatically deactivated.

Writing a health check

// dist/server/index.js (compiled plugin server entry)

export function register(registry) {
  // ... register hooks, routes, etc.
}

export async function healthCheck(registry) {
  // Return { healthy: true } or { healthy: false, message: '...' }
  try {
    await registry.settings.get('api_key'); // example: verify config
    return { healthy: true, message: 'All systems operational' };
  } catch (err) {
    return { healthy: false, message: err.message };
  }
}

Safe Mode

Set SAFE_MODE=true in your .env file to boot the server with all plugins disabled. This is useful for diagnosing plugin-related startup failures.

In safe mode:

  • No plugins are loaded at startup (both env-based and DB-based plugins are skipped).
  • The admin panel is fully accessible — a Safe Mode Active banner on the Plugins page indicates all plugins were skipped at startup.
  • You can still activate, deactivate, and manage plugins manually.

Startup Error Isolation

If a plugin fails to load during normal startup (not safe mode), the server:

  1. Logs the error with the plugin name and source.
  2. Auto-deactivates the plugin (isActive=false) and records the error in lastError.
  3. Continues loading remaining plugins without interruption.

This prevents crash loops — a failed plugin won’t retry on the next boot. The Plugins page shows a "Startup failed" badge for auto-deactivated plugins.

Circuit Breaker

The engine monitors runtime errors from plugin hook callbacks. If a plugin produces 50 or more errors within a 5-minute window, it is automatically deactivated to protect platform stability.

When the circuit breaker triggers:

  1. All plugin hooks, filters, and routes are removed immediately.
  2. The plugin is marked as inactive in the database with the reason in lastError.
  3. A plugin:auto-disabled WebSocket event is broadcast, removing the plugin’s frontend UI instantly.
  4. The Plugins page shows an "Auto-disabled" badge for the plugin.

An administrator must manually re-activate the plugin after investigating the issue.

Try the live demo Pricing

Have questions about Poker Engine? We reply fast.