refactor(core,shim): 统一基于 thiserror 的错误体系

- 移除 anyhow,使用 thiserror 定义强类型 Error 枚举
- 支持 #[from] 自动转换 mlua::Error,关键路径保留源码与上下文
- LuaRuntimeBuilder 采用惰性错误收集,简化链式初始化调用
- MirrorRegistry 实现规范化 FromLuaConversionError 错误转换
This commit is contained in:
2026-09-10 14:33:54 +08:00
parent 94b4c23299
commit 38dabd2ace
22 changed files with 686 additions and 482 deletions
+30 -20
View File
@@ -1,5 +1,5 @@
use crate::validators;
use mirror_core::error::validation_error;
use mirror_core::{conversion_err, validation_error};
use mlua::{FromLua, Lua, Value};
use std::collections::HashMap;
@@ -20,10 +20,14 @@ impl FromLua for MrCommand {
let root_tbl = match value {
Value::Table(t) => t,
other => {
return Err(validation_error(format!(
"commands 注册表的顶层配置必须是 Table,实际检测到: {}",
other.type_name()
)));
return Err(conversion_err(
other.type_name(),
"MrCommand",
format!(
"commands 注册表的顶层配置必须是 Table,实际检测到: {}",
other.type_name()
),
));
}
};
@@ -35,10 +39,14 @@ impl FromLua for MrCommand {
let cmd_name = validators::validate_command_name(&cmd_name)?;
// 2. 校验 entry 是否是 Table
if !cmd_entry.is_table() {
return Err(validation_error(format!(
"子命令 '{cmd_name}' 的配置必须是 Table,实际检测到: {}",
cmd_entry.type_name()
)));
return Err(conversion_err(
cmd_entry.type_name(),
"MrCommand",
format!(
"子命令 '{cmd_name}' 的配置必须是 Table,实际检测到: {}",
cmd_entry.type_name()
),
));
}
// 3. 直接交由子命令解析,外层负责补充错误上下文
let cmd_def = MrSubCommand::from_lua(cmd_entry, lua).map_err(|err| {
@@ -55,7 +63,7 @@ pub struct MrSubCommand {
/// 命令处理函数:必须是 Lua Function
pub(crate) module: String,
/// 命令行说明:必须是普通文本字符串
pub(crate) description: String ,
pub(crate) description: String,
}
impl FromLua for MrSubCommand {
@@ -63,10 +71,11 @@ impl FromLua for MrSubCommand {
let table = match value {
Value::Table(t) => t,
other => {
return Err(validation_error(format!(
"配置必须是 Table,实际检测到: {}",
other.type_name()
)));
return Err(conversion_err(
other.type_name(),
"MrSubCommand",
format!("配置必须是 Table,实际检测到: {}", other.type_name()),
));
}
};
// validators::LuaValidator::parse_command_entry(&tbl)
@@ -83,7 +92,7 @@ impl FromLua for MrSubCommand {
)));
}
}
let handler_val = table.get::<Value>("handler")?;
let module_val = table.get::<Value>("module")?;
// let handler_func = match handler_val {
// Value::Function(f) => f,
// Value::Boolean(true) => {
@@ -105,14 +114,15 @@ impl FromLua for MrSubCommand {
// )));
// }
// };
let module = match handler_val {
Value::Table(t) if t.get::<bool>("__is_lazy_command").unwrap_or(false) => {
t.get::<String>("module")?
let module = match module_val {
Value::String(s) => {
// 兜底归一化(防止用户手写 module = "a/b" 时未走 mr.command)
// 同时兼容直接写字符串的情况
s.to_str()?.replace(['/', '\\'], ".")
}
Value::String(s) => s.to_str()?.to_string(), // 同时兼容直接写字符串的情况
other => {
return Err(mlua::Error::runtime(format!(
"handler 必须通过 command(\"xxx\") 声明,实际为 {}",
"module 必须通过 mr.command(\"xxx\") 声明,实际为 {}",
other.type_name()
)));
}