Skip to main content

minco_workbench/
lib.rs

1//! Optional local presentation surfaces for bounded Minco project views.
2#![forbid(unsafe_code)]
3
4mod export;
5mod server;
6
7use minco_project_view::{
8    DerivedSummary, EdgeKind, InputUsage, ProjectIdentity, ProjectView, ViewLimits,
9};
10use serde::Serialize;
11use std::{collections::BTreeMap, fmt::Write as _};
12
13pub use export::{ExportFormat, ExportReport, ExportRequest, WorkbenchError, export_project_view};
14pub use server::{bind_loopback, serve_loopback};
15
16pub const WORKBENCH_SCHEMA_VERSION: u32 = 1;
17
18pub(crate) fn render_mermaid(view: &ProjectView) -> String {
19    let mut rendered = String::from("flowchart TD\n");
20    let mut node_indexes = BTreeMap::new();
21    for (index, node) in view.nodes.iter().enumerate() {
22        node_indexes.insert(node.id.as_str(), index);
23        let label = escape_mermaid_label(&node.label);
24        writeln!(&mut rendered, "  n{index}[{label}]").expect("writing to a String is infallible");
25    }
26    for edge in &view.edges {
27        let (Some(from), Some(to)) = (
28            node_indexes.get(edge.from.as_str()),
29            node_indexes.get(edge.to.as_str()),
30        ) else {
31            continue;
32        };
33        writeln!(
34            &mut rendered,
35            "  n{from} -->|{}| n{to}",
36            edge_kind(edge.kind)
37        )
38        .expect("writing to a String is infallible");
39    }
40    rendered
41}
42
43fn escape_mermaid_label(value: &str) -> String {
44    let escaped = value
45        .replace('&', "&")
46        .replace('<', "&lt;")
47        .replace('>', "&gt;");
48    serde_json::to_string(&escaped).expect("serializing a String is infallible")
49}
50
51const fn edge_kind(kind: EdgeKind) -> &'static str {
52    match kind {
53        EdgeKind::Contains => "contains",
54        EdgeKind::DependsOn => "depends_on",
55        EdgeKind::BelongsTo => "belongs_to",
56        EdgeKind::Implements => "implements",
57        EdgeKind::Exposes => "exposes",
58    }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
62pub struct WorkbenchCheckReport {
63    pub schema_version: u32,
64    pub status: &'static str,
65    pub mode: &'static str,
66    pub read_only: bool,
67    pub listening_sockets: usize,
68    pub writes: usize,
69    pub project: ProjectIdentity,
70    pub summary: DerivedSummary,
71    pub limits: ViewLimits,
72    pub input_usage: InputUsage,
73}
74
75#[must_use]
76pub fn check_report(view: &ProjectView) -> WorkbenchCheckReport {
77    WorkbenchCheckReport {
78        schema_version: WORKBENCH_SCHEMA_VERSION,
79        status: "ok",
80        mode: "check",
81        read_only: true,
82        listening_sockets: 0,
83        writes: 0,
84        project: view.project.clone(),
85        summary: view.summary.clone(),
86        limits: view.limits,
87        input_usage: view.input_usage.clone(),
88    }
89}