mirror of
https://github.com/insistence/RuoYi-Vue3-FastAPI.git
synced 2026-09-23 13:13:10 +00:00
* feat: 新增cli系统 * feat: ruoyi completion支持powershell * perf: 优化tui显示 * fix: 修复前端构建异常
240 lines
7.6 KiB
Python
240 lines
7.6 KiB
Python
import logging
|
|
from dataclasses import dataclass, field
|
|
from importlib import import_module
|
|
from typing import Any
|
|
|
|
from cli.context import CLI_CONTEXT_BUILDER, CliContext, CliContextBuilder
|
|
from cli.guards import (
|
|
DEFAULT_DANGEROUS_COMMAND_GUARD,
|
|
DEFAULT_DANGEROUS_COMMAND_RULE_REGISTRY,
|
|
DangerousCommandGuardService,
|
|
DangerousCommandRuleRegistry,
|
|
)
|
|
from cli.output import OutputRenderer
|
|
|
|
|
|
@dataclass
|
|
class CliRuntimeState:
|
|
"""
|
|
CLI 运行期状态。
|
|
|
|
:param logs_suppressed: 当前进程日志是否已切换为静默模式
|
|
"""
|
|
|
|
logs_suppressed: bool = False
|
|
sqlalchemy_logs_suppressed: bool = False
|
|
|
|
def get_logger(self) -> Any:
|
|
"""
|
|
获取 CLI 使用的日志对象。
|
|
|
|
:return: 日志对象
|
|
"""
|
|
return import_module('utils.log_util').logger
|
|
|
|
def suppress_logs(self) -> None:
|
|
"""
|
|
关闭 CLI 进程中的终端日志输出。
|
|
|
|
:return: None
|
|
"""
|
|
if self.logs_suppressed:
|
|
return
|
|
self.get_logger().remove()
|
|
self.logs_suppressed = True
|
|
|
|
def suppress_sqlalchemy_logs(self) -> None:
|
|
"""
|
|
关闭 CLI 进程中的 SQLAlchemy 终端 SQL 日志输出。
|
|
|
|
该逻辑同时处理两类来源:
|
|
|
|
1. 将 `config.env.DataBaseConfig.db_echo` 强制关闭,避免后续新建 Engine 时
|
|
继续打开 SQLAlchemy echo。
|
|
2. 将已知 SQLAlchemy logger 级别提升到 WARNING,避免已有 logger 配置把
|
|
`INFO sqlalchemy.engine.Engine ...` 继续打到标准输出。
|
|
|
|
:return: None
|
|
"""
|
|
if self.sqlalchemy_logs_suppressed:
|
|
return
|
|
env_module = import_module('config.env')
|
|
database_config = getattr(env_module, 'DataBaseConfig', None)
|
|
if database_config is not None and hasattr(database_config, 'db_echo'):
|
|
database_config.db_echo = False
|
|
for logger_name in (
|
|
'sqlalchemy',
|
|
'sqlalchemy.engine',
|
|
'sqlalchemy.engine.Engine',
|
|
'sqlalchemy.pool',
|
|
):
|
|
logging.getLogger(logger_name).setLevel(logging.WARNING)
|
|
self.sqlalchemy_logs_suppressed = True
|
|
|
|
|
|
@dataclass
|
|
class CliLogPolicy:
|
|
"""
|
|
CLI 日志策略服务。
|
|
|
|
该对象负责在上下文构建前应用统一的日志输出策略,
|
|
将“是否静默日志”这一策略从上下文工厂主体中拆出。
|
|
|
|
:param runtime_state: CLI 运行期状态对象
|
|
"""
|
|
|
|
runtime_state: CliRuntimeState
|
|
|
|
def prepare_regular_command(self) -> None:
|
|
"""
|
|
为普通 CLI 命令应用默认日志策略。
|
|
|
|
:return: None
|
|
"""
|
|
self.runtime_state.suppress_logs()
|
|
self.runtime_state.suppress_sqlalchemy_logs()
|
|
|
|
|
|
@dataclass
|
|
class DangerousCommandContextSupport:
|
|
"""
|
|
危险命令上下文支持服务。
|
|
|
|
该对象负责危险命令规则查询、保护执行与拒绝结果收口,
|
|
让上下文工厂本体只保留装配职责。
|
|
|
|
:param dangerous_command_rule_registry: 危险命令规则注册表
|
|
:param dangerous_command_guard_service: 危险命令保护执行服务
|
|
:param output_renderer: 输出渲染器
|
|
"""
|
|
|
|
dangerous_command_rule_registry: DangerousCommandRuleRegistry
|
|
dangerous_command_guard_service: DangerousCommandGuardService
|
|
output_renderer: OutputRenderer
|
|
|
|
def guard_context(self, ctx: CliContext, *, command_name: str) -> CliContext:
|
|
"""
|
|
对危险命令上下文执行统一保护。
|
|
|
|
:param ctx: 已构建的 CLI 上下文
|
|
:param command_name: 命令唯一标识
|
|
:return: 通过保护后的 CLI 上下文
|
|
"""
|
|
rule = self.dangerous_command_rule_registry.require_rule(command_name)
|
|
guard_result = self.dangerous_command_guard_service.guard(ctx, rule=rule)
|
|
if guard_result is not None:
|
|
self.output_renderer.complete_command(guard_result, ctx)
|
|
return ctx
|
|
|
|
|
|
@dataclass
|
|
class CliContextFactory:
|
|
"""
|
|
统一构建 CLI 命令上下文。
|
|
|
|
:param runtime_state: CLI 运行期状态对象
|
|
:param output_renderer: 输出渲染器
|
|
:param cli_context_builder: CLI 上下文构建器
|
|
:param dangerous_command_rule_registry: 危险命令规则注册表
|
|
:param dangerous_command_guard_service: 危险命令保护执行服务
|
|
"""
|
|
|
|
runtime_state: CliRuntimeState = field(default_factory=CliRuntimeState)
|
|
output_renderer: OutputRenderer = field(default_factory=OutputRenderer)
|
|
cli_context_builder: CliContextBuilder = field(default_factory=lambda: CLI_CONTEXT_BUILDER)
|
|
dangerous_command_rule_registry: DangerousCommandRuleRegistry = field(
|
|
default_factory=lambda: DEFAULT_DANGEROUS_COMMAND_RULE_REGISTRY
|
|
)
|
|
dangerous_command_guard_service: DangerousCommandGuardService = field(
|
|
default_factory=lambda: DEFAULT_DANGEROUS_COMMAND_GUARD
|
|
)
|
|
_log_policy: CliLogPolicy | None = field(default=None, init=False, repr=False)
|
|
_dangerous_command_support: DangerousCommandContextSupport | None = field(
|
|
default=None,
|
|
init=False,
|
|
repr=False,
|
|
)
|
|
|
|
def get_log_policy(self) -> CliLogPolicy:
|
|
"""
|
|
获取当前上下文工厂使用的日志策略服务。
|
|
|
|
:return: CLI 日志策略服务
|
|
"""
|
|
if self._log_policy is None:
|
|
self._log_policy = CliLogPolicy(runtime_state=self.runtime_state)
|
|
return self._log_policy
|
|
|
|
def get_dangerous_command_support(self) -> DangerousCommandContextSupport:
|
|
"""
|
|
获取当前上下文工厂使用的危险命令上下文支持服务。
|
|
|
|
:return: 危险命令上下文支持服务
|
|
"""
|
|
if self._dangerous_command_support is None:
|
|
self._dangerous_command_support = DangerousCommandContextSupport(
|
|
dangerous_command_rule_registry=self.dangerous_command_rule_registry,
|
|
dangerous_command_guard_service=self.dangerous_command_guard_service,
|
|
output_renderer=self.output_renderer,
|
|
)
|
|
return self._dangerous_command_support
|
|
|
|
def build_regular(
|
|
self,
|
|
env: str,
|
|
output: str,
|
|
allow_prod: bool,
|
|
yes: bool,
|
|
dry_run: bool,
|
|
) -> CliContext:
|
|
"""
|
|
构建普通命令上下文。
|
|
|
|
:param env: 运行环境
|
|
:param output: 输出格式
|
|
:param allow_prod: 是否允许生产环境危险命令
|
|
:param yes: 是否跳过确认
|
|
:param dry_run: 是否演练执行
|
|
:return: CLI 上下文
|
|
"""
|
|
self.get_log_policy().prepare_regular_command()
|
|
return self.cli_context_builder.build(env, output, allow_prod, yes, dry_run)
|
|
|
|
def build_readonly(
|
|
self,
|
|
env: str,
|
|
output: str,
|
|
) -> CliContext:
|
|
"""
|
|
构建只读命令上下文。
|
|
|
|
:param env: 运行环境
|
|
:param output: 输出格式
|
|
:return: CLI 上下文
|
|
"""
|
|
return self.build_regular(env, output, False, False, False)
|
|
|
|
def build_dangerous(
|
|
self,
|
|
env: str,
|
|
output: str,
|
|
allow_prod: bool,
|
|
yes: bool,
|
|
dry_run: bool,
|
|
*,
|
|
command_name: str,
|
|
) -> CliContext:
|
|
"""
|
|
构建危险命令上下文并执行统一保护。
|
|
|
|
:param env: 运行环境
|
|
:param output: 输出格式
|
|
:param allow_prod: 是否允许生产环境危险命令
|
|
:param yes: 是否跳过确认
|
|
:param dry_run: 是否演练执行
|
|
:param command_name: 命令唯一标识
|
|
:return: CLI 上下文
|
|
"""
|
|
ctx = self.build_regular(env, output, allow_prod, yes, dry_run)
|
|
return self.get_dangerous_command_support().guard_context(ctx, command_name=command_name)
|