Add plugin platform with modular backend and frontend registry.
Split graph/import/meta into Django apps, add API v1 with OpenAPI and pytest, and introduce plugin registry with the tags reference plugin on both FE and BE. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PluginsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'plugins'
|
||||
|
||||
def ready(self):
|
||||
import plugins.registry # noqa: F401
|
||||
@@ -0,0 +1,48 @@
|
||||
"""Plugin platform base classes and registry."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import URLPattern
|
||||
|
||||
|
||||
class Plugin(ABC):
|
||||
id: str = ''
|
||||
version: str = '1.0.0'
|
||||
min_core_version: str = '1.0.0'
|
||||
permissions: List[str] = []
|
||||
|
||||
@abstractmethod
|
||||
def urlpatterns(self) -> List[URLPattern]:
|
||||
pass
|
||||
|
||||
def installed_apps(self) -> List[str]:
|
||||
return []
|
||||
|
||||
|
||||
_REGISTRY: dict[str, Plugin] = {}
|
||||
|
||||
|
||||
def register_plugin(plugin: Plugin) -> None:
|
||||
_REGISTRY[plugin.id] = plugin
|
||||
|
||||
|
||||
def get_plugin(plugin_id: str) -> Plugin | None:
|
||||
return _REGISTRY.get(plugin_id)
|
||||
|
||||
|
||||
def get_enabled_plugins() -> List[Plugin]:
|
||||
enabled = getattr(settings, 'ENABLED_PLUGINS', [])
|
||||
return [_REGISTRY[pid] for pid in enabled if pid in _REGISTRY]
|
||||
|
||||
|
||||
def plugin_urlpatterns() -> List[URLPattern]:
|
||||
from django.urls import path, include
|
||||
|
||||
patterns: List[URLPattern] = []
|
||||
for plugin in get_enabled_plugins():
|
||||
patterns.append(
|
||||
path(f'plugins/{plugin.id}/', include((plugin.urlpatterns(), plugin.id)))
|
||||
)
|
||||
return patterns
|
||||
@@ -0,0 +1,6 @@
|
||||
"""Register built-in plugins."""
|
||||
|
||||
from plugins.base import register_plugin
|
||||
from plugins_tags.plugin import TagsPlugin
|
||||
|
||||
register_plugin(TagsPlugin())
|
||||
@@ -0,0 +1,9 @@
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
from .base import plugin_urlpatterns
|
||||
|
||||
urlpatterns = [
|
||||
path('plugins/', views.plugin_manifest, name='plugin-manifest'),
|
||||
*plugin_urlpatterns(),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
from django.urls import path
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.response import Response
|
||||
|
||||
from plugins.base import get_enabled_plugins
|
||||
|
||||
|
||||
@api_view(['GET'])
|
||||
def plugin_manifest(request):
|
||||
"""List enabled plugins and their metadata."""
|
||||
return Response([
|
||||
{
|
||||
'id': p.id,
|
||||
'version': p.version,
|
||||
'min_core_version': p.min_core_version,
|
||||
'permissions': p.permissions,
|
||||
}
|
||||
for p in get_enabled_plugins()
|
||||
])
|
||||
Reference in New Issue
Block a user