Add .env.example with configuration for database, Redis, security, SMTP, workers, and plugins. Add .gitignore for Python, Node.js, Next.js, Docker volumes, and IDE files. Add MIT License. Update README.md with feature overview, quick start guide, architecture description, plugin system documentation, security details, backup/restore instructions, and developer setup. Add Alembic configuration files and placeholder directories for API, web, worker, and plugin components
178 lines
4.7 KiB
Markdown
178 lines
4.7 KiB
Markdown
# NexaDash Plugin Developer Documentation
|
|
|
|
## Table of Contents
|
|
|
|
1. [What is a NexaDash Plugin?](#what-is-a-nexadash-plugin)
|
|
2. [Plugin Structure](#plugin-structure)
|
|
3. [Manifest](#manifest)
|
|
4. [Settings & Credentials Schema](#settings--credentials-schema)
|
|
5. [Widget Schema](#widget-schema)
|
|
6. [Backend Connector](#backend-connector)
|
|
7. [Frontend Widget](#frontend-widget)
|
|
8. [Permissions](#permissions)
|
|
9. [Secrets Handling](#secrets-handling)
|
|
10. [Background Jobs](#background-jobs)
|
|
11. [Error Handling](#error-handling)
|
|
12. [Versioning](#versioning)
|
|
13. [Testing](#testing)
|
|
14. [Security Rules](#security-rules)
|
|
15. [Example: Creating a Plugin](#example-creating-a-plugin)
|
|
16. [Packaging](#packaging)
|
|
17. [Upload](#upload)
|
|
18. [Best Practices](#best-practices)
|
|
|
|
## What is a NexaDash Plugin?
|
|
|
|
A NexaDash plugin is a declarative package that connects an external service to the dashboard. It defines:
|
|
|
|
- A `plugin.manifest.json` describing metadata, schemas and widgets.
|
|
- A backend connector (declarative or built-in Python class) that fetches data from the service.
|
|
- Optional frontend widget components that render the data.
|
|
|
|
Plugins never execute arbitrary code in the main API process. Connectors are loaded from a known registry and run in a sandboxed layer.
|
|
|
|
## Plugin Structure
|
|
|
|
```text
|
|
my-plugin/
|
|
plugin.manifest.json
|
|
README.md
|
|
widgets/
|
|
MyWidget.tsx
|
|
connector/
|
|
connector.py (optional, for custom Python connectors)
|
|
```
|
|
|
|
## Manifest
|
|
|
|
```json
|
|
{
|
|
"id": "my-plugin",
|
|
"name": "My Plugin",
|
|
"version": "1.0.0",
|
|
"nexadashPluginApi": "1.0",
|
|
"description": "Short description",
|
|
"author": "Your Name",
|
|
"category": "Infrastructure",
|
|
"permissions": ["network:outbound", "secrets:read"],
|
|
"settingsSchema": {},
|
|
"credentialsSchema": {},
|
|
"widgets": [],
|
|
"apiRoutes": [],
|
|
"hasFrontend": true,
|
|
"healthcheck": {
|
|
"method": "GET",
|
|
"intervalSeconds": 60,
|
|
"timeoutSeconds": 30
|
|
}
|
|
}
|
|
```
|
|
|
|
## Settings & Credentials Schema
|
|
|
|
Schemas follow JSON Schema with a few conventions:
|
|
|
|
- `format: "password"` hides the value in the UI.
|
|
- `enum` renders as a select dropdown.
|
|
- Credentials are stored encrypted and never returned to the frontend.
|
|
|
|
## Widget Schema
|
|
|
|
Each widget needs:
|
|
|
|
- `id`: unique widget type identifier.
|
|
- `name`: human-readable label.
|
|
- `description`: short help text.
|
|
- `defaultWidth`, `defaultHeight`: default grid size.
|
|
- `settingsSchema`: per-widget settings.
|
|
|
|
## Backend Connector
|
|
|
|
Built-in connectors cover many services. For custom services, you can provide a Python class that extends `PluginConnector`:
|
|
|
|
```python
|
|
from apps.api.src.plugins.base import PluginConnector
|
|
|
|
class MyConnector(PluginConnector):
|
|
id = "my-plugin"
|
|
name = "My Plugin"
|
|
|
|
async def healthcheck(self):
|
|
return {"status": "ok"}
|
|
|
|
async def fetch_widget_data(self, widget_type, settings):
|
|
return {"value": 42}
|
|
```
|
|
|
|
Register it in `apps/api/src/plugins/registry.py`.
|
|
|
|
## Frontend Widget
|
|
|
|
Frontend widgets are React components that receive `data` and `settings` props. They are rendered by the dashboard editor.
|
|
|
|
## Permissions
|
|
|
|
Common permissions:
|
|
|
|
- `network:outbound` — plugin may make HTTP requests.
|
|
- `secrets:read` — plugin may decrypt its own credentials.
|
|
- `jobs:schedule` — plugin may schedule background jobs.
|
|
|
|
## Secrets Handling
|
|
|
|
Never log or return secrets. The backend decrypts credentials only when executing a connector and passes them to the connector instance.
|
|
|
|
## Background Jobs
|
|
|
|
Use the Celery worker for long-running sync tasks. Schedule via the `background_jobs` API or from a connector.
|
|
|
|
## Error Handling
|
|
|
|
Return `{status: "error", message: "..."}` on failures. The dashboard shows a user-friendly error card.
|
|
|
|
## Versioning
|
|
|
|
Use semantic versioning. The plugin registry tracks versions in `plugin_versions`.
|
|
|
|
## Testing
|
|
|
|
- Validate the manifest with `@nexadash/plugin-sdk`.
|
|
- Test connectors with mocked HTTP clients.
|
|
- Add API tests for custom endpoints.
|
|
|
|
## Security Rules
|
|
|
|
- Only `http`/`https` URLs are allowed (SSRF protection).
|
|
- No credentials in frontend code.
|
|
- No dynamic code execution (`eval`, `exec`).
|
|
- Use least-privilege API tokens.
|
|
- Validate all inputs with schemas.
|
|
|
|
## Example: Creating a Plugin
|
|
|
|
See `plugins/example-plugin/` for a complete working example.
|
|
|
|
## Packaging
|
|
|
|
Zip the plugin directory with the manifest at the root:
|
|
|
|
```bash
|
|
zip -r my-plugin.zip my-plugin/
|
|
```
|
|
|
|
## Upload
|
|
|
|
Upload the ZIP in the UI under **Plugins → Upload Plugin** or via the API:
|
|
|
|
```bash
|
|
curl -F "file=@my-plugin.zip" https://nexadash.local/api/v1/plugins/upload
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
- Keep widgets focused on one metric.
|
|
- Use pagination for large lists.
|
|
- Cache expensive requests in the connector.
|
|
- Provide clear error messages.
|
|
- Document required credentials.
|