Skip to main content

dioxus_component_manifest/
lib.rs

1use std::process::Command;
2
3use schemars::{schema_for, JsonSchema, Schema};
4use serde::{Deserialize, Serialize};
5
6/// A component compatible with the dioxus components system.
7/// This may be a "virtual" component which is empty except for a list of members.
8#[derive(Deserialize, Serialize, JsonSchema, Clone, Debug, PartialEq, Eq, Hash)]
9#[serde(rename_all = "camelCase", deny_unknown_fields)]
10pub struct Component {
11    pub name: String,
12
13    #[serde(default)]
14    pub description: String,
15
16    #[serde(default, skip_serializing_if = "Vec::is_empty")]
17    pub authors: Vec<String>,
18
19    #[serde(default, skip_serializing_if = "Vec::is_empty")]
20    pub component_dependencies: Vec<ComponentDependency>,
21
22    #[serde(default, skip_serializing_if = "Vec::is_empty")]
23    pub cargo_dependencies: Vec<CargoDependency>,
24
25    #[serde(default, skip_serializing_if = "Vec::is_empty")]
26    pub members: Vec<String>,
27
28    #[serde(default, skip_serializing_if = "Vec::is_empty")]
29    pub exclude: Vec<String>,
30
31    #[serde(default, skip_serializing_if = "Vec::is_empty")]
32    pub global_assets: Vec<String>,
33}
34
35/// A dependency on another component, either built-in or third-party.
36#[derive(Deserialize, Serialize, JsonSchema, Clone, Debug, PartialEq, Eq, Hash)]
37#[serde(untagged)]
38pub enum ComponentDependency {
39    Builtin(String),
40    ThirdParty {
41        name: String,
42        git: String,
43        #[serde(default)]
44        rev: Option<String>,
45    },
46}
47
48/// A dependency on a cargo crate required for a component.
49#[derive(Deserialize, Serialize, JsonSchema, Clone, Debug, PartialEq, Eq, Hash)]
50#[serde(untagged)]
51pub enum CargoDependency {
52    Simple(String),
53    Detailed {
54        name: String,
55        #[serde(default)]
56        version: Option<String>,
57        #[serde(default, skip_serializing_if = "Vec::is_empty")]
58        features: Vec<String>,
59        #[serde(default, skip_serializing_if = "std::ops::Not::not")]
60        default_features: bool,
61        #[serde(default, skip_serializing_if = "Option::is_none")]
62        git: Option<String>,
63        #[serde(default, skip_serializing_if = "Option::is_none")]
64        rev: Option<String>,
65    },
66}
67
68impl CargoDependency {
69    /// Get the `cargo add` command for this dependency.
70    pub fn add_command(&self) -> Command {
71        let mut cmd = Command::new("cargo");
72        cmd.arg("add");
73        match self {
74            CargoDependency::Simple(name) => {
75                cmd.arg(name);
76            }
77            CargoDependency::Detailed {
78                name,
79                version,
80                features,
81                default_features,
82                git,
83                rev,
84            } => {
85                cmd.arg(format!(
86                    "{name}{}",
87                    version
88                        .as_ref()
89                        .map(|version| format!("@{version}"))
90                        .unwrap_or_default()
91                ));
92                if !features.is_empty() {
93                    cmd.arg("--features").arg(features.join(","));
94                }
95                if !*default_features {
96                    cmd.arg("--no-default-features");
97                }
98                if let Some(git) = git {
99                    cmd.arg("--git").arg(git);
100                }
101                if let Some(rev) = rev {
102                    cmd.arg("--rev").arg(rev);
103                }
104            }
105        }
106        cmd
107    }
108
109    /// Get the name of the dependency.
110    pub fn name(&self) -> &str {
111        match self {
112            CargoDependency::Simple(name) => name,
113            CargoDependency::Detailed { name, .. } => name,
114        }
115    }
116}
117
118/// Get the JSON schema for the `Component` struct.
119pub fn component_manifest_schema() -> Schema {
120    schema_for!(Component)
121}