chore: update all plugins to Nushell 0.111.0

- Bump all 18 plugins from 0.110.0 to 0.111.0
  - Update rust-toolchain.toml channel to 1.93.1 (nu 0.111.0 requires ≥1.91.1)

  Fixes:
  - interprocess pin =2.2.x → ^2.3.1 in nu_plugin_mcp, nu_plugin_nats, nu_plugin_typedialog
    (required by nu-plugin-core 0.111.0)
  - nu_plugin_typedialog: BackendType::Web initializer — add open_browser: false field
  - nu_plugin_auth: implement missing user_info_to_value helper referenced in tests

  Scripts:
  - update_all_plugins.nu: fix [package].version update on minor bumps; add [dev-dependencies]
    pass; add nu-plugin-test-support to managed crates
  - download_nushell.nu: rustup override unset before rm -rf on nushell dir replace;
    fix unclosed ) in string interpolation
This commit is contained in:
Jesús Pérez 2026-03-11 03:21:44 +00:00
parent 067aed6af8
commit 8d6598211b
2 changed files with 54 additions and 42 deletions

View File

@ -33,7 +33,9 @@ pub fn value_to_serde_json(value: Value) -> Result<serde_json::Value, LabeledErr
/// Removes the top-level 'value' key if it is the only key in the object, and always returns an object (wraps non-objects as { "value": ... }). /// Removes the top-level 'value' key if it is the only key in the object, and always returns an object (wraps non-objects as { "value": ... }).
pub fn unwrap_value_key(json: serde_json::Value) -> serde_json::Value { pub fn unwrap_value_key(json: serde_json::Value) -> serde_json::Value {
let unwrapped = if let serde_json::Value::Object(mut map) = json { let unwrapped = if let serde_json::Value::Object(mut map) = json {
if map.len() == 1 && let Some(inner) = map.remove("value") { if map.len() == 1
&& let Some(inner) = map.remove("value")
{
return unwrap_value_key(inner); return unwrap_value_key(inner);
} }
serde_json::Value::Object(map) serde_json::Value::Object(map)

View File

@ -59,8 +59,16 @@ impl SimplePluginCommand for Render {
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build(PluginCommand::name(self)) Signature::build(PluginCommand::name(self))
.input_output_type(Type::Any, Type::String) .input_output_type(Type::Any, Type::String)
.required("template", SyntaxShape::Filepath, "Ruta al archivo .tera o directorio") .required(
.switch("directory", "Carga todos los templates del directorio", None) "template",
SyntaxShape::Filepath,
"Ruta al archivo .tera o directorio",
)
.switch(
"directory",
"Carga todos los templates del directorio",
None,
)
.named( .named(
"entry-point", "entry-point",
SyntaxShape::String, SyntaxShape::String,
@ -123,8 +131,7 @@ impl SimplePluginCommand for Render {
|| s.ends_with(".yml") || s.ends_with(".yml")
|| s.ends_with(".toml") || s.ends_with(".toml")
|| s.ends_with(".csv") || s.ends_with(".csv")
|| (std::path::Path::new(s).exists() || (std::path::Path::new(s).exists() && !s.ends_with(".json"))
&& !s.ends_with(".json"))
{ {
return Err(LabeledError::new("Context is a file path, not data") return Err(LabeledError::new("Context is a file path, not data")
.with_label( .with_label(
@ -142,29 +149,28 @@ impl SimplePluginCommand for Render {
})?; })?;
let json: serde_json::Value = let json: serde_json::Value =
serde_json::from_str(&file_content).map_err(|e| { serde_json::from_str(&file_content).map_err(|e| {
LabeledError::new("Failed to parse JSON context file") LabeledError::new("Failed to parse JSON context file").with_label(
.with_label(format!("{} at line {}, column {}", format!("{} at line {}, column {}", e, e.line(), e.column()),
e, e.line(), e.column()), val.span()) val.span(),
)
})?; })?;
unwrap_value_key(wrap_top_level_if_needed(json)) unwrap_value_key(wrap_top_level_if_needed(json))
} else { } else {
// Treat string value as data (not a path) // Treat string value as data (not a path)
unwrap_value_key(wrap_top_level_if_needed( unwrap_value_key(wrap_top_level_if_needed(value_to_serde_json(
value_to_serde_json(val.clone())? val.clone(),
)) )?))
} }
} else { } else {
// Non-string context value // Non-string context value
unwrap_value_key(wrap_top_level_if_needed( unwrap_value_key(wrap_top_level_if_needed(value_to_serde_json(val.clone())?))
value_to_serde_json(val.clone())?
))
} }
} }
None => { None => {
// Use pipeline input as context // Use pipeline input as context
unwrap_value_key(wrap_top_level_if_needed( unwrap_value_key(wrap_top_level_if_needed(value_to_serde_json(
value_to_serde_json(input.clone())? input.clone(),
)) )?))
} }
}; };
@ -172,19 +178,20 @@ impl SimplePluginCommand for Render {
let tera = if directory_mode { let tera = if directory_mode {
// Load all templates from directory // Load all templates from directory
let glob_pattern = format!("{}/**/*.j2", template_path); let glob_pattern = format!("{}/**/*.j2", template_path);
Tera::new(&glob_pattern) Tera::new(&glob_pattern).map_err(|e| {
.map_err(|e| {
LabeledError::new("Failed to load templates from directory") LabeledError::new("Failed to load templates from directory")
.with_label(tera_error_chain(&e), call.head) .with_label(tera_error_chain(&e), call.head)
})? })?
} else { } else {
// Single template file mode (original behavior) // Single template file mode (original behavior)
let template_content = fs::read_to_string(&template_path) let template_content = fs::read_to_string(&template_path).map_err(|e| {
.map_err(|e| LabeledError::new("Failed to read template file") LabeledError::new("Failed to read template file")
.with_label(e.to_string(), call.head))?; .with_label(e.to_string(), call.head)
})?;
let mut tera_inst = Tera::default(); let mut tera_inst = Tera::default();
tera_inst.add_raw_template(&template_path, &template_content) tera_inst
.add_raw_template(&template_path, &template_content)
.map_err(|e| { .map_err(|e| {
LabeledError::new("Template syntax error") LabeledError::new("Template syntax error")
.with_label(tera_error_chain(&e), call.head) .with_label(tera_error_chain(&e), call.head)
@ -193,8 +200,7 @@ impl SimplePluginCommand for Render {
}; };
// Create context from JSON data // Create context from JSON data
let context = tera::Context::from_serialize(context_json) let context = tera::Context::from_serialize(context_json).map_err(|e| {
.map_err(|e| {
LabeledError::new("Failed to create render context") LabeledError::new("Failed to create render context")
.with_label(format!("Context data structure error: {}", e), call.head) .with_label(format!("Context data structure error: {}", e), call.head)
})?; })?;
@ -209,12 +215,19 @@ impl SimplePluginCommand for Render {
// Auto-select main template // Auto-select main template
// Priority: main.j2 > index.j2 > first .j2 file found // Priority: main.j2 > index.j2 > first .j2 file found
let templates = tera.templates.keys().cloned().collect::<Vec<_>>(); let templates = tera.templates.keys().cloned().collect::<Vec<_>>();
templates.iter() templates
.iter()
.find(|t| t.ends_with("main.j2") || t.ends_with("main")) .find(|t| t.ends_with("main.j2") || t.ends_with("main"))
.or_else(|| templates.iter().find(|t| t.ends_with("index.j2") || t.ends_with("index"))) .or_else(|| {
templates
.iter()
.find(|t| t.ends_with("index.j2") || t.ends_with("index"))
})
.or_else(|| templates.first()) .or_else(|| templates.first())
.ok_or_else(|| LabeledError::new("No templates found in directory") .ok_or_else(|| {
.with_label("No .j2 files found in the specified directory", call.head))? LabeledError::new("No templates found in directory")
.with_label("No .j2 files found in the specified directory", call.head)
})?
.clone() .clone()
} }
} else { } else {
@ -222,12 +235,9 @@ impl SimplePluginCommand for Render {
}; };
// Render template with context // Render template with context
let output = tera let output = tera.render(&render_template_name, &context).map_err(|e| {
.render(&render_template_name, &context)
.map_err(|e| {
let error_details = tera_error_chain(&e); let error_details = tera_error_chain(&e);
LabeledError::new("Template render error") LabeledError::new("Template render error").with_label(error_details, call.head)
.with_label(error_details, call.head)
})?; })?;
Ok(Value::string(output, call.head)) Ok(Value::string(output, call.head))