mirror of
https://github.com/insistence/RuoYi-Vue3-FastAPI.git
synced 2026-09-25 21:57:49 +00:00
* feat: 初始化插件系统 * refactor: 收口插件系统运行时重构 * perf: 优化插件系统类型提示 * fix&perf: 修复和优化插件系统 * fix: 修复gitignore规则误忽略插件文件的问题 * fix: 修复运行时插件根路径算错的问题 * fix: 加强插件发现和路由注册的防护措施 * revert: 回滚定时任务白名单 * fix: 移除未使用的应用路由注册探测 * revert: 恢复部分代码 * perf: 优化插件系统 * docs: 新增插件开发文档 * perf: 优化插件管理模块 * perf: 提升插件系统核心能力 * refactor: 重构生命周期 step runner * fix: 修复lint错误 * test: 清理测试用例 * test: 调整测试目录名称 * fix: 修复前后端目录硬编码的问题 * fix: 修复插件系统安全性缺口 * refactor: 重新设计插件生命周期 Migration 事务与回滚 * perf: 优化插件系统边界问题 * refactor: 重构当前插件系统的依赖体系设计 * perf: 优化代码 * perf: 优化代码 * fix: 修复代码合并问题 * fix: 修复bug * perf: 优化代码 * perf&fix: 优化代码和修复bug * docs: 优化文档格式 * feat: 适配Vue2版本 * docs: 更新README文档 * fix: 修复ruff lint错误 * chore: 更新后端依赖文件
206 lines
7.7 KiB
Python
206 lines
7.7 KiB
Python
from collections.abc import Callable
|
|
from typing import Annotated, Any, Literal
|
|
|
|
import typer
|
|
|
|
from cli.context import AllowProdOption, DryRunOption, EnvOption, OutputOption, YesOption
|
|
from cli.groups.plugin.options import (
|
|
PluginDependencyAllowlistExampleCommandOptions,
|
|
PluginDependencyInstallCommandOptions,
|
|
PluginDependencyLockCommandOptions,
|
|
)
|
|
|
|
PluginPrecheckOperation = Literal['install', 'enable', 'upgrade', 'uninstall', 'purge']
|
|
PluginPlanOperation = Literal['install', 'enable', 'upgrade']
|
|
|
|
|
|
def register_dependency_commands(app: typer.Typer, get_controller: Callable[[], Any]) -> None:
|
|
"""
|
|
注册插件依赖、预检和计划命令。
|
|
|
|
:param app: Typer 命令组
|
|
:param get_controller: 插件命令控制器工厂
|
|
:return: None
|
|
"""
|
|
|
|
@app.command('check-deps', help='检查插件依赖')
|
|
def check_deps_command(
|
|
plugin_id: Annotated[str, typer.Argument(help='插件ID')],
|
|
env: EnvOption = 'dev',
|
|
output: OutputOption = 'text',
|
|
) -> None:
|
|
"""
|
|
检查插件依赖。
|
|
|
|
:param plugin_id: 插件ID
|
|
:param env: 当前命令运行环境
|
|
:param output: 输出格式
|
|
:return: None
|
|
"""
|
|
get_controller().check_plugin_dependencies(plugin_id, env, output)
|
|
|
|
@app.command('precheck', help='执行插件操作预检')
|
|
def precheck_command(
|
|
operation: Annotated[
|
|
PluginPrecheckOperation,
|
|
typer.Argument(help='预检操作类型:install、enable、upgrade、uninstall 或 purge'),
|
|
],
|
|
plugin_id: Annotated[str, typer.Argument(help='插件ID')],
|
|
env: EnvOption = 'dev',
|
|
output: OutputOption = 'text',
|
|
) -> None:
|
|
"""
|
|
执行插件操作预检。
|
|
|
|
:param operation: 预检操作类型
|
|
:param plugin_id: 插件ID
|
|
:param env: 当前命令运行环境
|
|
:param output: 输出格式
|
|
:return: None
|
|
"""
|
|
get_controller().precheck_plugin(operation, plugin_id, env, output)
|
|
|
|
@app.command('plan', help='生成插件批量操作拓扑计划')
|
|
def plan_command(
|
|
operation: Annotated[PluginPlanOperation, typer.Argument(help='计划操作类型:install、enable 或 upgrade')],
|
|
plugin_ids: Annotated[list[str] | None, typer.Argument(help='插件ID列表,不传则计划全部插件')] = None,
|
|
env: EnvOption = 'dev',
|
|
output: OutputOption = 'text',
|
|
) -> None:
|
|
"""
|
|
生成插件批量操作拓扑计划。
|
|
|
|
:param operation: 计划操作类型
|
|
:param plugin_ids: 插件ID列表
|
|
:param env: 当前命令运行环境
|
|
:param output: 输出格式
|
|
:return: None
|
|
"""
|
|
get_controller().plan_plugins(operation, plugin_ids or [], env, output)
|
|
|
|
@app.command('install-deps', help='安装插件依赖')
|
|
def install_deps_command( # noqa: PLR0913
|
|
plugin_id: Annotated[str, typer.Argument(help='插件ID')],
|
|
*,
|
|
env: EnvOption = 'dev',
|
|
output: OutputOption = 'text',
|
|
allow_prod: AllowProdOption = False,
|
|
yes: YesOption = False,
|
|
dry_run: DryRunOption = False,
|
|
policy_mode: Annotated[
|
|
Literal['disabled', 'plan_only', 'explicit', 'locked', 'offline'] | None,
|
|
typer.Option('--policy-mode', help='临时覆盖插件依赖安装策略模式'),
|
|
] = None,
|
|
allow_unlisted: Annotated[
|
|
bool,
|
|
typer.Option('--allow-unlisted', help='dev 环境允许未命中 allowlist 的依赖仅告警'),
|
|
] = False,
|
|
lockfile: Annotated[str, typer.Option('--lockfile', help='指定插件依赖锁文件路径')] = '',
|
|
offline_dir: Annotated[str, typer.Option('--offline-dir', help='指定插件离线依赖制品目录')] = '',
|
|
require_lockfile: Annotated[
|
|
bool | None,
|
|
typer.Option('--require-lockfile/--no-require-lockfile', help='临时切换锁文件要求'),
|
|
] = None,
|
|
) -> None:
|
|
"""
|
|
安装插件依赖。
|
|
|
|
:param plugin_id: 插件ID
|
|
:param env: 当前命令运行环境
|
|
:param output: 输出格式
|
|
:param allow_prod: 是否允许生产环境危险命令
|
|
:param yes: 是否跳过确认
|
|
:param dry_run: 是否仅预演
|
|
:param policy_mode: 临时覆盖策略模式
|
|
:param allow_unlisted: dev 环境是否允许未命中 allowlist 的依赖仅告警
|
|
:param lockfile: 锁文件路径
|
|
:param offline_dir: 离线制品目录
|
|
:param require_lockfile: 是否要求锁文件
|
|
:return: None
|
|
"""
|
|
get_controller().install_plugin_dependencies(
|
|
plugin_id,
|
|
env,
|
|
output,
|
|
options=PluginDependencyInstallCommandOptions(
|
|
allow_prod=allow_prod,
|
|
yes=yes,
|
|
dry_run=dry_run,
|
|
policy_mode=policy_mode,
|
|
allow_unlisted=allow_unlisted,
|
|
lockfile=lockfile,
|
|
offline_dir=offline_dir,
|
|
require_lockfile=require_lockfile,
|
|
),
|
|
)
|
|
|
|
@app.command('lock-deps', help='生成插件依赖锁文件模板')
|
|
def lock_deps_command(
|
|
plugin_id: Annotated[str, typer.Argument(help='插件ID')],
|
|
env: EnvOption = 'dev',
|
|
output: OutputOption = 'text',
|
|
dry_run: DryRunOption = False,
|
|
output_path: Annotated[
|
|
str,
|
|
typer.Option('--output-path', help='输出锁文件路径,默认写入插件目录 plugin.lock.yaml'),
|
|
] = '',
|
|
offline_dir: Annotated[
|
|
str, typer.Option('--offline-dir', help='从本地离线制品目录反填版本和 hash/integrity')
|
|
] = '',
|
|
overwrite: Annotated[bool, typer.Option('--overwrite', help='覆盖已有锁文件')] = False,
|
|
) -> None:
|
|
"""
|
|
生成插件依赖锁文件模板。
|
|
|
|
:param plugin_id: 插件ID
|
|
:param env: 当前命令运行环境
|
|
:param output: 输出格式
|
|
:param dry_run: 是否仅预演
|
|
:param output_path: 输出锁文件路径
|
|
:param offline_dir: 离线制品目录
|
|
:param overwrite: 是否覆盖已有锁文件
|
|
:return: None
|
|
"""
|
|
get_controller().lock_plugin_dependencies(
|
|
plugin_id,
|
|
env,
|
|
output,
|
|
options=PluginDependencyLockCommandOptions(
|
|
output_path=output_path,
|
|
offline_dir=offline_dir,
|
|
dry_run=dry_run,
|
|
overwrite=overwrite,
|
|
),
|
|
)
|
|
|
|
@app.command('allowlist-example', help='生成插件依赖允许列表示例')
|
|
def allowlist_example_command(
|
|
env: EnvOption = 'dev',
|
|
output: OutputOption = 'text',
|
|
dry_run: DryRunOption = False,
|
|
output_path: Annotated[
|
|
str,
|
|
typer.Option('--output-path', help='输出允许列表路径,默认写入 config/plugin_dependency_allowlist.yaml'),
|
|
] = '',
|
|
overwrite: Annotated[bool, typer.Option('--overwrite', help='覆盖已有允许列表文件')] = False,
|
|
) -> None:
|
|
"""
|
|
生成插件依赖允许列表示例。
|
|
|
|
:param env: 当前命令运行环境
|
|
:param output: 输出格式
|
|
:param dry_run: 是否仅预演
|
|
:param output_path: 输出允许列表路径
|
|
:param overwrite: 是否覆盖已有允许列表文件
|
|
:return: None
|
|
"""
|
|
get_controller().generate_plugin_dependency_allowlist_example(
|
|
env,
|
|
output,
|
|
options=PluginDependencyAllowlistExampleCommandOptions(
|
|
output_path=output_path,
|
|
dry_run=dry_run,
|
|
overwrite=overwrite,
|
|
),
|
|
)
|