diff --git a/shopdb/__init__.py b/shopdb/__init__.py index d11db33..7eab542 100644 --- a/shopdb/__init__.py +++ b/shopdb/__init__.py @@ -80,6 +80,7 @@ CORE_BLUEPRINT_NAMES = ( 'auth', 'assets', 'machinetypes', + 'plugins', 'vendors', 'models', 'businessunits', diff --git a/shopdb/core/api/__init__.py b/shopdb/core/api/__init__.py index 9f6ccd4..f6d9385 100644 --- a/shopdb/core/api/__init__.py +++ b/shopdb/core/api/__init__.py @@ -3,6 +3,7 @@ from .auth import auth_bp from .assets import assets_bp from .machinetypes import machinetypes_bp +from .plugins import plugins_bp from .vendors import vendors_bp from .models import models_bp from .businessunits import businessunits_bp @@ -24,6 +25,7 @@ __all__ = [ 'auth_bp', 'assets_bp', 'machinetypes_bp', + 'plugins_bp', 'vendors_bp', 'models_bp', 'businessunits_bp', diff --git a/shopdb/core/api/plugins.py b/shopdb/core/api/plugins.py new file mode 100644 index 0000000..419177e --- /dev/null +++ b/shopdb/core/api/plugins.py @@ -0,0 +1,37 @@ +"""Plugin introspection API - what plugins are loaded and their contracts.""" + +from flask import Blueprint, current_app +from flask_jwt_extended import jwt_required + +from shopdb.utils.responses import success_response + +plugins_bp = Blueprint('plugins', __name__) + + +@plugins_bp.route('', methods=['GET']) +@jwt_required(optional=True) +def list_plugins(): + """List loaded plugins with their manifest metadata + the framework + contract version they were checked against.""" + from shopdb import __contract_version__ + pm = current_app.extensions.get('plugin_manager') + plugins = [] + if pm: + for name, plugin in pm.get_all_plugins().items(): + meta = plugin.meta + plugins.append({ + 'name': meta.name, + 'version': meta.version, + 'description': meta.description, + 'author': meta.author, + 'core_version': meta.core_version, + 'api_prefix': meta.api_prefix, + 'dependencies': meta.dependencies, + }) + plugins.sort(key=lambda p: p['name']) + + return success_response({ + 'contract_version': __contract_version__, + 'count': len(plugins), + 'plugins': plugins, + }) diff --git a/shopdb/plugins/base.py b/shopdb/plugins/base.py index 640f1c7..b0ec814 100644 --- a/shopdb/plugins/base.py +++ b/shopdb/plugins/base.py @@ -15,7 +15,8 @@ class PluginMeta: description: str author: str = "" dependencies: List[str] = field(default_factory=list) - core_version: str = ">=1.0.0" + # Default to the current pre-1.0 contract range; tighten when 1.0 lands + core_version: str = ">=0.2.0,<1.0.0" api_prefix: str = None def __post_init__(self):