use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use uuid::Uuid;
use std::path::PathBuf;
use apimock_routing::view::RouteCatalogSnapshot;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct NodeId(pub Uuid);
impl NodeId {
pub fn new() -> Self {
Self(Uuid::new_v4())
}
}
impl Default for NodeId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for NodeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone, Debug, Serialize)]
#[non_exhaustive]
pub struct WorkspaceSnapshot {
pub files: Vec<ConfigFileView>,
pub routes: RouteCatalogSnapshot,
pub diagnostics: Vec<Diagnostic>,
}
impl WorkspaceSnapshot {
pub fn empty() -> Self {
Self {
files: Vec::new(),
routes: RouteCatalogSnapshot::empty(),
diagnostics: Vec::new(),
}
}
}
#[derive(Clone, Debug, Serialize)]
#[non_exhaustive]
pub struct ConfigFileView {
pub path: PathBuf,
pub display_name: String,
pub kind: ConfigFileKind,
pub nodes: Vec<ConfigNodeView>,
}
#[derive(Clone, Copy, Debug, Serialize)]
pub enum ConfigFileKind {
Root,
RuleSet,
Middleware,
}
#[derive(Clone, Debug, Serialize)]
#[non_exhaustive]
pub struct ConfigNodeView {
pub id: NodeId,
pub source_file: PathBuf,
pub toml_path: String,
pub display_name: String,
pub kind: NodeKind,
pub validation: NodeValidation,
}
#[derive(Clone, Copy, Debug, Serialize)]
pub enum NodeKind {
RootSetting,
RuleSet,
Rule,
Respond,
FileNode,
Script,
}
#[derive(Clone, Debug, Default, Serialize)]
pub struct NodeValidation {
pub ok: bool,
pub issues: Vec<ValidationIssue>,
}
impl NodeValidation {
pub fn ok() -> Self {
Self {
ok: true,
issues: Vec::new(),
}
}
}
#[derive(Clone, Debug, Serialize)]
pub struct ValidationIssue {
pub severity: Severity,
pub message: String,
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum EditCommand {
AddRuleSet {
path: String,
},
RemoveRuleSet {
id: NodeId,
},
AddRule {
parent: NodeId,
rule: RulePayload,
},
UpdateRule {
id: NodeId,
rule: RulePayload,
},
DeleteRule {
id: NodeId,
},
MoveRule {
id: NodeId,
new_index: usize,
},
UpdateRespond {
id: NodeId,
respond: RespondPayload,
},
UpdateRootSetting {
key: RootSettingKey,
value: EditValue,
},
}
#[derive(Clone, Debug, Default)]
pub struct RulePayload {
pub url_path: Option<String>,
pub method: Option<String>,
pub respond: RespondPayload,
}
#[derive(Clone, Debug, Default)]
pub struct RespondPayload {
pub file_path: Option<String>,
pub text: Option<String>,
pub status: Option<u16>,
pub delay_milliseconds: Option<u32>,
}
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum RootSettingKey {
ListenerIpAddress,
ListenerPort,
ServiceFallbackRespondDir,
ServiceStrategy,
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum EditValue {
String(String),
Integer(i64),
Boolean(bool),
StringList(Vec<String>),
Enum(String),
Json(JsonValue),
}
#[derive(Clone, Debug, Serialize)]
#[non_exhaustive]
pub struct ApplyResult {
pub changed_nodes: Vec<NodeId>,
pub diagnostics: Vec<Diagnostic>,
pub requires_reload: bool,
}
#[derive(Clone, Debug, Serialize)]
#[non_exhaustive]
pub struct SaveResult {
pub changed_files: Vec<PathBuf>,
pub diff_summary: Vec<DiffItem>,
pub requires_reload: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct DiffItem {
pub kind: DiffKind,
pub target: NodeId,
pub summary: String,
}
#[derive(Clone, Copy, Debug, Serialize)]
pub enum DiffKind {
Added,
Updated,
Removed,
}
#[derive(Clone, Debug, Serialize)]
pub struct ValidationReport {
pub diagnostics: Vec<Diagnostic>,
pub is_valid: bool,
}
impl ValidationReport {
pub fn ok() -> Self {
Self {
diagnostics: Vec::new(),
is_valid: true,
}
}
}
#[derive(Clone, Debug, Serialize)]
pub struct Diagnostic {
pub node_id: Option<NodeId>,
pub file: Option<PathBuf>,
pub severity: Severity,
pub message: String,
}
#[derive(Clone, Copy, Debug, Serialize)]
pub enum Severity {
Error,
Warning,
Info,
}
#[derive(Clone, Copy, Debug, Default, Serialize)]
pub struct ReloadHint {
pub requires_reload: bool,
pub requires_restart: bool,
}
impl ReloadHint {
pub fn none() -> Self {
Self::default()
}
pub fn reload() -> Self {
Self {
requires_reload: true,
requires_restart: false,
}
}
pub fn restart() -> Self {
Self {
requires_reload: false,
requires_restart: true,
}
}
}