dfx_core/config/
project_templates.rs1use crate::config::model::project_template::ProjectTemplateCategory;
2use itertools::Itertools;
3use std::collections::BTreeMap;
4use std::fmt::Display;
5use std::io;
6use std::path::PathBuf;
7use std::sync::OnceLock;
8
9type GetArchiveFn = fn() -> Result<tar::Archive<flate2::read::GzDecoder<&'static [u8]>>, io::Error>;
10
11#[derive(Debug, Clone)]
12pub enum ResourceLocation {
13 Bundled { get_archive_fn: GetArchiveFn },
15
16 Directory { path: PathBuf },
18}
19
20#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
21pub struct ProjectTemplateName(pub String);
22
23impl Display for ProjectTemplateName {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}", self.0)
26 }
27}
28
29#[derive(Debug, Clone)]
30pub struct ProjectTemplate {
31 pub name: ProjectTemplateName,
34
35 pub display: String,
37
38 pub resource_location: ResourceLocation,
40
41 pub category: ProjectTemplateCategory,
44
45 pub requirements: Vec<ProjectTemplateName>,
47
48 pub post_create: Vec<String>,
50
51 pub post_create_spinner_message: Option<String>,
53
54 pub post_create_failure_warning: Option<String>,
56
57 pub sort_order: u32,
77}
78
79type ProjectTemplates = BTreeMap<ProjectTemplateName, ProjectTemplate>;
80
81static PROJECT_TEMPLATES: OnceLock<ProjectTemplates> = OnceLock::new();
82
83pub fn populate(builtin_templates: Vec<ProjectTemplate>, loaded_templates: Vec<ProjectTemplate>) {
84 let templates: ProjectTemplates = builtin_templates
85 .into_iter()
86 .map(|t| (t.name.clone(), t))
87 .chain(loaded_templates.into_iter().map(|t| (t.name.clone(), t)))
88 .collect();
89
90 PROJECT_TEMPLATES.set(templates).unwrap();
91}
92
93pub fn get_project_template(name: &ProjectTemplateName) -> ProjectTemplate {
94 PROJECT_TEMPLATES.get().unwrap().get(name).cloned().unwrap()
95}
96
97pub fn find_project_template(name: &ProjectTemplateName) -> Option<ProjectTemplate> {
98 PROJECT_TEMPLATES.get().unwrap().get(name).cloned()
99}
100
101pub fn get_sorted_templates(category: ProjectTemplateCategory) -> Vec<ProjectTemplate> {
102 PROJECT_TEMPLATES
103 .get()
104 .unwrap()
105 .values()
106 .filter(|t| t.category == category)
107 .cloned()
108 .sorted_by(|a, b| {
109 a.sort_order
110 .cmp(&b.sort_order)
111 .then_with(|| a.display.cmp(&b.display))
112 })
113 .collect()
114}
115
116pub fn project_template_cli_names(category: ProjectTemplateCategory) -> Vec<String> {
117 PROJECT_TEMPLATES
118 .get()
119 .map(|templates| {
120 templates
121 .values()
122 .filter(|t| t.category == category)
123 .map(|t| t.name.0.clone())
124 .collect()
125 })
126 .unwrap_or_default()
127}