use crate::platform::model::PIPELINE_DEFINITION_EXTENSION;
use crate::platform::services::project::virtual_path_from_file_rel_path;
pub fn pipeline_editor_url(owner: &str, project: &str, name: &str) -> String {
let file_rel_path = pipeline_file_id(name);
let virtual_path = virtual_path_from_file_rel_path(&file_rel_path);
format!(
"/projects/{owner}/{project}/pipelines/registry?type=pipeline&path={virtual_path}&file={file_rel_path}"
)
}
fn pipeline_file_id(name: &str) -> String {
let rel = name.trim().trim_start_matches('/');
if rel.ends_with(PIPELINE_DEFINITION_EXTENSION) {
return rel.to_string();
}
let stem = rel.strip_suffix(".json").unwrap_or(rel);
format!("{stem}{PIPELINE_DEFINITION_EXTENSION}")
}
pub fn match_patterns(dsl: &str, owner: &str, project: &str) -> Option<String> {
let first_cmd = dsl.split("&&").next().unwrap_or(dsl).trim();
let lower = first_cmd.to_lowercase();
let tokens: Vec<&str> = first_cmd.split_whitespace().collect();
if lower.starts_with("register ") {
let name = tokens.get(1).copied().unwrap_or("");
if !name.is_empty() {
return Some(pipeline_editor_url(owner, project, name));
}
}
for verb in ["activate", "deactivate", "describe", "patch", "execute"] {
if lower.starts_with(&format!("{verb} pipeline ")) {
let name = tokens.get(2).copied().unwrap_or("");
if !name.is_empty() {
return Some(pipeline_editor_url(owner, project, name));
}
}
}
if lower.starts_with("get templates") {
return Some(format!("/projects/{owner}/{project}/build/templates"));
}
if lower.starts_with("get pipelines") {
return Some(format!("/projects/{owner}/{project}/pipelines/registry"));
}
if lower.starts_with("describe connection ") {
let slug = tokens.get(2).copied().unwrap_or("");
if !slug.is_empty() {
return Some(format!("/projects/{owner}/{project}/db?slug={slug}"));
}
}
if lower.contains("pg.query") {
return Some(format!("/projects/{owner}/{project}/db"));
}
if lower.starts_with("get connections") {
return Some(format!("/projects/{owner}/{project}/db/connections"));
}
if lower.starts_with("get credentials") {
return Some(format!("/projects/{owner}/{project}/credentials"));
}
if lower.starts_with("get docs") {
return Some(format!("/projects/{owner}/{project}/build/docs"));
}
if lower.starts_with("get nodes") {
return Some(format!("/projects/{owner}/{project}/build/nodes"));
}
if lower.starts_with("get tables") {
return Some(format!("/projects/{owner}/{project}/db"));
}
if lower.starts_with("describe node ") {
return Some(format!("/projects/{owner}/{project}/build/nodes"));
}
if lower.starts_with("git ") {
return Some(format!("/projects/{owner}/{project}/files"));
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_pipeline_command_opens_the_pipeline_in_the_unified_editor() {
let expected = "/projects/o/p/pipelines/registry?type=pipeline&path=/pipelines/test&file=pipelines/test/demo.zf.json";
assert_eq!(
match_patterns("register pipelines/test/demo | trigger.manual", "o", "p").as_deref(),
Some(expected)
);
for dsl in [
"activate pipeline pipelines/test/demo",
"deactivate pipeline pipelines/test/demo.zf.json",
"describe pipeline pipelines/test/demo.json",
"patch pipeline pipelines/test/demo node b --optional",
"execute pipeline pipelines/test/demo --input '{}'",
"register pipelines/test/demo | trigger.manual && activate pipeline pipelines/test/demo",
] {
assert_eq!(match_patterns(dsl, "o", "p").as_deref(), Some(expected), "{dsl}");
}
assert_eq!(
pipeline_editor_url("o", "p", "demo"),
"/projects/o/p/pipelines/registry?type=pipeline&path=/&file=demo.zf.json"
);
assert!(!match_patterns("register x | trigger.manual", "o", "p")
.unwrap()
.contains("pipelines/editor"));
}
}