1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::path::Path;
4use std::str::FromStr;
5use std::{fmt, fs};
6
7use serde::de::DeserializeOwned;
8use serde::{Deserialize, Serialize};
9use storm_workspace::utils::get_workspace_root;
10
11use crate::types::PackageJson;
12use crate::{Config, ConfigError, Environment, File, Value};
13
14#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
15#[serde(rename_all = "lowercase")]
16pub enum WorkspaceMode {
17 Development,
18 Test,
19 Production,
20}
21
22impl Default for WorkspaceMode {
23 fn default() -> Self {
24 WorkspaceMode::Production
25 }
26}
27
28impl FromStr for WorkspaceMode {
29 type Err = ();
30
31 fn from_str(input: &str) -> Result<WorkspaceMode, Self::Err> {
32 match input {
33 "development" => Ok(WorkspaceMode::Development),
34 "test" => Ok(WorkspaceMode::Test),
35 "production" => Ok(WorkspaceMode::Production),
36 _ => Err(()),
37 }
38 }
39}
40
41impl fmt::Display for WorkspaceMode {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 match *self {
44 WorkspaceMode::Development => write!(f, "development"),
45 WorkspaceMode::Test => write!(f, "test"),
46 WorkspaceMode::Production => write!(f, "production"),
47 }
48 }
49}
50
51#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
52#[serde(rename_all = "lowercase")]
53pub enum WorkspaceVariant {
54 Minimal,
55 Monorepo,
56}
57
58impl Default for WorkspaceVariant {
59 fn default() -> Self {
60 WorkspaceVariant::Monorepo
61 }
62}
63
64impl FromStr for WorkspaceVariant {
65 type Err = ();
66
67 fn from_str(input: &str) -> Result<WorkspaceVariant, Self::Err> {
68 match input {
69 "minimal" => Ok(WorkspaceVariant::Minimal),
70 "monorepo" => Ok(WorkspaceVariant::Monorepo),
71 _ => Err(()),
72 }
73 }
74}
75
76impl fmt::Display for WorkspaceVariant {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 match *self {
79 WorkspaceVariant::Minimal => write!(f, "minimal"),
80 WorkspaceVariant::Monorepo => write!(f, "monorepo"),
81 }
82 }
83}
84
85#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
86#[serde(rename_all = "lowercase")]
87pub enum PackageManagerType {
88 Npm,
89 Yarn,
90 Pnpm,
91 Bun,
92}
93
94impl FromStr for PackageManagerType {
95 type Err = ();
96
97 fn from_str(input: &str) -> Result<PackageManagerType, Self::Err> {
98 match input {
99 "npm" => Ok(PackageManagerType::Npm),
100 "yarn" => Ok(PackageManagerType::Yarn),
101 "pnpm" => Ok(PackageManagerType::Pnpm),
102 "bun" => Ok(PackageManagerType::Bun),
103 _ => Err(()),
104 }
105 }
106}
107
108impl fmt::Display for PackageManagerType {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 match *self {
111 PackageManagerType::Npm => write!(f, "npm"),
112 PackageManagerType::Yarn => write!(f, "yarn"),
113 PackageManagerType::Pnpm => write!(f, "pnpm"),
114 PackageManagerType::Bun => write!(f, "bun"),
115 }
116 }
117}
118
119#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
120#[serde(rename_all = "lowercase")]
121pub enum LogLevel {
122 Silent,
123 Fatal,
124 Error,
125 Warn,
126 Success,
127 Info,
128 Debug,
129 Trace,
130 All,
131}
132
133impl FromStr for LogLevel {
134 type Err = ();
135
136 fn from_str(input: &str) -> Result<LogLevel, Self::Err> {
137 match input {
138 "silent" => Ok(LogLevel::Silent),
139 "fatal" => Ok(LogLevel::Fatal),
140 "error" => Ok(LogLevel::Error),
141 "warn" => Ok(LogLevel::Warn),
142 "success" => Ok(LogLevel::Success),
143 "info" => Ok(LogLevel::Info),
144 "debug" => Ok(LogLevel::Debug),
145 "trace" => Ok(LogLevel::Trace),
146 "all" => Ok(LogLevel::All),
147 _ => Err(()),
148 }
149 }
150}
151
152impl fmt::Display for LogLevel {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 match *self {
155 LogLevel::Silent => write!(f, "silent"),
156 LogLevel::Fatal => write!(f, "fatal"),
157 LogLevel::Error => write!(f, "error"),
158 LogLevel::Warn => write!(f, "warn"),
159 LogLevel::Success => write!(f, "success"),
160 LogLevel::Info => write!(f, "info"),
161 LogLevel::Debug => write!(f, "debug"),
162 LogLevel::Trace => write!(f, "trace"),
163 LogLevel::All => write!(f, "all"),
164 }
165 }
166}
167
168#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
169#[serde(untagged)]
170pub enum ExtendsConfig {
171 Single(String),
172 Multiple(Vec<String>),
173}
174
175#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
176#[serde(rename_all = "camelCase")]
177pub struct OrganizationDetails {
178 pub name: Option<String>,
180 pub description: Option<String>,
182 pub logo: Option<String>,
184 pub icon: Option<String>,
186 pub url: Option<String>,
188}
189
190#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
191#[serde(untagged)]
192pub enum WorkspaceOrganizationConfig {
193 Details(OrganizationDetails),
194 Name(String),
195}
196
197impl Default for WorkspaceOrganizationConfig {
198 fn default() -> Self {
199 WorkspaceOrganizationConfig::Name("storm-software".to_string())
200 }
201}
202
203#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
204#[serde(rename_all = "camelCase")]
205pub struct ColorPaletteConfig {
206 pub dark: String,
208 pub light: String,
210 pub brand: String,
212 pub alternate: Option<String>,
214 pub accent: Option<String>,
216 pub link: String,
218 pub help: String,
220 pub success: String,
222 pub info: String,
224 pub warning: String,
226 pub danger: String,
228 pub fatal: Option<String>,
230 pub positive: String,
232 pub negative: String,
234 pub gradient: Option<Vec<String>>,
236}
237
238impl Default for ColorPaletteConfig {
239 fn default() -> Self {
240 Self {
241 dark: "#151718".to_string(),
242 light: "#cbd5e1".to_string(),
243 brand: "#1fb2a6".to_string(),
244 alternate: None,
245 accent: None,
246 link: "#3fa6ff".to_string(),
247 help: "#818cf8".to_string(),
248 success: "#45b27e".to_string(),
249 info: "#38bdf8".to_string(),
250 warning: "#f3d371".to_string(),
251 danger: "#d8314a".to_string(),
252 fatal: None,
253 positive: "#4ade80".to_string(),
254 negative: "#ef4444".to_string(),
255 gradient: None,
256 }
257 }
258}
259
260#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
261#[serde(rename_all = "camelCase")]
262pub struct ColorSchemaConfig {
263 pub foreground: String,
265 pub background: String,
267 pub brand: String,
269 pub alternate: Option<String>,
271 pub accent: Option<String>,
273 pub link: String,
275 pub help: String,
277 pub success: String,
279 pub info: String,
281 pub warning: String,
283 pub danger: String,
285 pub fatal: Option<String>,
287 pub positive: String,
289 pub negative: String,
291 pub gradient: Option<Vec<String>>,
293}
294
295impl ColorSchemaConfig {
296 fn default_dark() -> Self {
297 Self {
298 foreground: "#cbd5e1".to_string(),
299 background: "#151718".to_string(),
300 brand: "#1fb2a6".to_string(),
301 alternate: None,
302 accent: None,
303 link: "#3fa6ff".to_string(),
304 help: "#818cf8".to_string(),
305 success: "#45b27e".to_string(),
306 info: "#38bdf8".to_string(),
307 warning: "#f3d371".to_string(),
308 danger: "#d8314a".to_string(),
309 fatal: None,
310 positive: "#4ade80".to_string(),
311 negative: "#ef4444".to_string(),
312 gradient: None,
313 }
314 }
315
316 fn default_light() -> Self {
317 Self {
318 foreground: "#151718".to_string(),
319 background: "#cbd5e1".to_string(),
320 brand: "#1fb2a6".to_string(),
321 alternate: None,
322 accent: None,
323 link: "#3fa6ff".to_string(),
324 help: "#818cf8".to_string(),
325 success: "#45b27e".to_string(),
326 info: "#38bdf8".to_string(),
327 warning: "#f3d371".to_string(),
328 danger: "#d8314a".to_string(),
329 fatal: None,
330 positive: "#4ade80".to_string(),
331 negative: "#ef4444".to_string(),
332 gradient: None,
333 }
334 }
335}
336
337impl Default for ColorSchemaConfig {
338 fn default() -> Self {
339 ColorSchemaConfig::default_dark()
340 }
341}
342
343#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
344#[serde(rename_all = "camelCase")]
345pub struct ColorThemeConfig {
346 pub light: ColorSchemaConfig,
348 pub dark: ColorSchemaConfig,
350}
351
352impl Default for ColorThemeConfig {
353 fn default() -> Self {
354 Self { light: ColorSchemaConfig::default_light(), dark: ColorSchemaConfig::default_dark() }
355 }
356}
357
358#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
359#[serde(untagged)]
360pub enum ColorThemeEntry {
361 Palette(ColorPaletteConfig),
362 Theme(ColorThemeConfig),
363}
364
365#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
366#[serde(untagged)]
367pub enum WorkspaceColorsConfig {
368 Palette(ColorPaletteConfig),
369 Theme(ColorThemeConfig),
370 Collection(HashMap<String, ColorThemeEntry>),
371}
372
373impl Default for WorkspaceColorsConfig {
374 fn default() -> Self {
375 WorkspaceColorsConfig::Palette(ColorPaletteConfig::default())
376 }
377}
378
379#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
380#[serde(rename_all = "camelCase")]
381pub struct WorkspaceRegistryUrlConfig {
382 pub github: Option<String>,
384 pub npm: Option<String>,
386 pub cargo: Option<String>,
388 pub cyclone: Option<String>,
390 pub container: Option<String>,
392}
393
394#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
395#[serde(rename_all = "camelCase")]
396pub struct WorkspaceBotConfig {
397 pub name: String,
399 pub email: String,
401}
402
403impl Default for WorkspaceBotConfig {
404 fn default() -> Self {
405 Self { name: "stormie-bot".to_string(), email: "stormie-bot@stormsoftware.com".to_string() }
406 }
407}
408
409#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
410#[serde(rename_all = "camelCase")]
411pub struct WorkspaceReleaseBannerConfig {
412 pub url: Option<String>,
414 pub alt: String,
416}
417
418impl Default for WorkspaceReleaseBannerConfig {
419 fn default() -> Self {
420 Self { url: None, alt: "The workspace's banner image".to_string() }
421 }
422}
423
424#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
425#[serde(untagged)]
426pub enum ReleaseBannerConfig {
427 Url(String),
428 Details(WorkspaceReleaseBannerConfig),
429}
430
431impl Default for ReleaseBannerConfig {
432 fn default() -> Self {
433 ReleaseBannerConfig::Details(WorkspaceReleaseBannerConfig::default())
434 }
435}
436
437#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
438#[serde(rename_all = "camelCase")]
439pub struct WorkspaceReleaseConfig {
440 pub banner: ReleaseBannerConfig,
442 pub header: Option<String>,
444 pub footer: Option<String>,
446}
447
448impl Default for WorkspaceReleaseConfig {
449 fn default() -> Self {
450 Self { banner: ReleaseBannerConfig::default(), header: None, footer: None }
451 }
452}
453
454#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
455#[serde(rename_all = "camelCase")]
456pub struct WorkspaceSocialsConfig {
457 pub twitter: Option<String>,
459 pub discord: Option<String>,
461 pub telegram: Option<String>,
463 pub slack: Option<String>,
465 pub medium: Option<String>,
467 pub github: Option<String>,
469}
470
471#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
472#[serde(rename_all = "camelCase")]
473pub struct WorkspaceErrorConfig {
474 pub codes_file: String,
476 pub url: Option<String>,
478}
479
480impl Default for WorkspaceErrorConfig {
481 fn default() -> Self {
482 Self { codes_file: "tools/errors/codes.json".to_string(), url: None }
483 }
484}
485
486#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
487#[serde(rename_all = "camelCase")]
488pub struct WorkspaceDirectoriesConfig {
489 pub cache: Option<String>,
491 pub data: Option<String>,
493 pub config: Option<String>,
495 pub temp: Option<String>,
497 pub log: Option<String>,
499 pub build: String,
501}
502
503impl Default for WorkspaceDirectoriesConfig {
504 fn default() -> Self {
505 Self { cache: None, data: None, config: None, temp: None, log: None, build: "dist".to_string() }
506 }
507}
508
509#[derive(Debug, Clone)]
512pub struct WorkspaceConfig {
513 pub schema: String,
515 pub config: Option<Config>,
517 pub config_file: Option<String>,
519 pub extends: Option<ExtendsConfig>,
521 pub workspace_root: String,
523 pub name: String,
525 pub namespace: String,
527 pub variant: WorkspaceVariant,
529 pub organization: WorkspaceOrganizationConfig,
531 pub repository: String,
533 pub license: String,
535 pub homepage: String,
537 pub docs: Option<String>,
539 pub portal: Option<String>,
541 pub licensing: Option<String>,
543 pub contact: Option<String>,
545 pub support: Option<String>,
547 pub branch: String,
549 pub preid: Option<String>,
551 pub owner: String,
553 pub bot: WorkspaceBotConfig,
555 pub mode: WorkspaceMode,
557 pub colors: WorkspaceColorsConfig,
559 pub release: WorkspaceReleaseConfig,
561 pub socials: WorkspaceSocialsConfig,
563 pub error: WorkspaceErrorConfig,
565 pub skip_cache: bool,
567 pub registry: WorkspaceRegistryUrlConfig,
569 pub directories: WorkspaceDirectoriesConfig,
571 pub package_manager: PackageManagerType,
573 pub timezone: String,
575 pub locale: String,
577 pub log_level: LogLevel,
579 pub skip_config_logging: bool,
581 pub extensions: RefCell<HashMap<String, HashMap<String, Value>>>,
583}
584
585impl WorkspaceConfig {
586 pub fn new() -> Result<Self, ConfigError> {
587 let workspace_root = get_workspace_root().expect("No workspace root could be found");
588 let workspace_config = Self::from_workspace_root(&workspace_root)?;
589
590 Ok(workspace_config)
591 }
592
593 pub fn from_workspace_root(workspace_root: &Path) -> Result<Self, ConfigError> {
594 let mut workspace_config = Self::default();
595 workspace_config.workspace_root = workspace_root.to_str().unwrap().to_string();
596
597 match fs::metadata(format!("{}/package.json", workspace_root.to_string_lossy())) {
598 Ok(_) => {
599 let package_json_path = format!("{}/package.json", workspace_root.to_string_lossy());
600
601 let package_json: PackageJson = serde_json::from_reader(
602 std::fs::File::open(Path::new(&package_json_path))
603 .expect("Unable to read package.json file"),
604 )
605 .expect("error while reading or parsing");
606
607 workspace_config.config = Some(
608 Config::builder()
609 .set_default("name", package_json.name)?
610 .set_default("namespace", package_json.namespace)?
611 .set_default("repository", package_json.repository.get("url").unwrap().to_string())?
612 .set_default("license", package_json.license)?
613 .set_default("homepage", package_json.homepage)?
614 .set_default("workspace_root", workspace_root.to_str().unwrap().to_string())?
615 .add_source(
616 File::with_name(&format!(
617 "{}/storm-workspace.json",
618 workspace_root.to_string_lossy()
619 ))
620 .required(false),
621 )
622 .add_source(
623 File::with_name(&format!(
624 "{}/storm-workspace.jsonc",
625 workspace_root.to_string_lossy()
626 ))
627 .required(false),
628 )
629 .add_source(
630 File::with_name(&format!("{}/.storm/config.json", workspace_root.to_string_lossy()))
631 .required(false),
632 )
633 .add_source(
634 File::with_name(&format!(
635 "{}/.storm-workspace/config.json",
636 workspace_root.to_string_lossy()
637 ))
638 .required(false),
639 )
640 .add_source(
641 File::with_name(&format!(
642 "{}/storm-workspace.toml",
643 workspace_root.to_string_lossy()
644 ))
645 .required(false),
646 )
647 .add_source(
648 File::with_name(&format!("{}/.storm/config.toml", workspace_root.to_string_lossy()))
649 .required(false),
650 )
651 .add_source(
652 File::with_name(&format!(
653 "{}/.storm-workspace/config.toml",
654 workspace_root.to_string_lossy()
655 ))
656 .required(false),
657 )
658 .add_source(
659 File::with_name(&format!(
660 "{}/storm-workspace.yaml",
661 workspace_root.to_string_lossy()
662 ))
663 .required(false),
664 )
665 .add_source(
666 File::with_name(&format!("{}/.storm/config.yaml", workspace_root.to_string_lossy()))
667 .required(false),
668 )
669 .add_source(
670 File::with_name(&format!(
671 "{}/.storm-workspace/config.yaml",
672 workspace_root.to_string_lossy()
673 ))
674 .required(false),
675 )
676 .add_source(
677 File::with_name(&format!("{}/storm-workspace.yml", workspace_root.to_string_lossy()))
678 .required(false),
679 )
680 .add_source(
681 File::with_name(&format!("{}/.storm/config.yml", workspace_root.to_string_lossy()))
682 .required(false),
683 )
684 .add_source(
685 File::with_name(&format!(
686 "{}/.storm-workspace/config.yml",
687 workspace_root.to_string_lossy()
688 ))
689 .required(false),
690 )
691 .add_source(Environment::with_prefix("storm"))
692 .build()?,
693 );
694
695 let config = workspace_config.config.as_ref().unwrap();
696 if let Ok(found) = config.get_string("config_file") {
697 workspace_config.config_file = Some(found);
698 }
699 if let Ok(found) = config.get_string("schema") {
700 workspace_config.schema = found;
701 }
702 if let Ok(found) = config.get::<ExtendsConfig>("extends") {
703 workspace_config.extends = Some(found);
704 }
705 if let Ok(found) = config.get_string("workspace_root") {
706 workspace_config.workspace_root = found;
707 }
708 if let Ok(found) = config.get_string("name") {
709 workspace_config.name = found;
710 }
711 if let Ok(found) = config.get_string("namespace") {
712 workspace_config.namespace = found;
713 }
714 if let Ok(found) = config.get::<WorkspaceVariant>("variant") {
715 workspace_config.variant = found;
716 }
717 if let Ok(found) = config.get::<WorkspaceOrganizationConfig>("organization") {
718 workspace_config.organization = found;
719 } else if let Ok(found) = config.get::<WorkspaceOrganizationConfig>("org") {
720 workspace_config.organization = found;
721 } else if let Ok(found) = config.get::<WorkspaceOrganizationConfig>("organization_config") {
722 workspace_config.organization = found;
723 }
724 if let Ok(found) = config.get_string("repository") {
725 workspace_config.repository = found;
726 }
727 if let Ok(found) = config.get_string("license") {
728 workspace_config.license = found;
729 }
730 if let Ok(found) = config.get_string("homepage") {
731 workspace_config.homepage = found;
732 }
733 if let Ok(found) = config.get_string("docs") {
734 workspace_config.docs = Some(found);
735 }
736 if let Ok(found) = config.get_string("portal") {
737 workspace_config.portal = Some(found);
738 }
739 if let Ok(found) = config.get_string("licensing") {
740 workspace_config.licensing = Some(found);
741 }
742 if let Ok(found) = config.get_string("contact") {
743 workspace_config.contact = Some(found);
744 }
745 if let Ok(found) = config.get_string("support") {
746 workspace_config.support = Some(found);
747 }
748 if let Ok(found) = config.get_string("branch") {
749 workspace_config.branch = found;
750 }
751 if let Ok(found) = config.get_string("preid") {
752 workspace_config.preid = Some(found);
753 }
754 if let Ok(found) = config.get_string("owner") {
755 workspace_config.owner = found;
756 }
757 if let Ok(found) = config.get_string("mode") {
758 workspace_config.mode = WorkspaceMode::from_str(&found).unwrap();
759 }
760 if let Ok(found) = config.get_bool("skip_cache") {
761 workspace_config.skip_cache = found;
762 }
763 if let Ok(found) = config.get_string("package_manager") {
764 workspace_config.package_manager = PackageManagerType::from_str(&found).unwrap();
765 }
766 if let Ok(found) = config.get_string("timezone") {
767 workspace_config.timezone = found;
768 }
769 if let Ok(found) = config.get_string("locale") {
770 workspace_config.locale = found;
771 }
772 if let Ok(found) = config.get_string("log_level") {
773 workspace_config.log_level = LogLevel::from_str(&found).unwrap();
774 }
775 if let Ok(found) = config.get_bool("skip_config_logging") {
776 workspace_config.skip_config_logging = found;
777 }
778 if let Ok(found) = config.get::<WorkspaceReleaseConfig>("release") {
779 workspace_config.release = found;
780 }
781 if let Ok(found) = config.get::<WorkspaceColorsConfig>("colors") {
782 workspace_config.colors = found;
783 }
784 if let Ok(found) = config.get::<WorkspaceBotConfig>("bot") {
785 workspace_config.bot = found;
786 } else if let Ok(found) = config.get::<WorkspaceBotConfig>("bot_config") {
787 workspace_config.bot = found;
788 } else if let Ok(found) = config.get::<WorkspaceBotConfig>("workspaceBot") {
789 workspace_config.bot = found;
790 }
791 if let Ok(found) = config.get::<WorkspaceSocialsConfig>("socials") {
792 workspace_config.socials = found;
793 }
794 if let Ok(found) = config.get::<WorkspaceErrorConfig>("error") {
795 workspace_config.error = found;
796 }
797 if let Ok(found) = config.get::<WorkspaceRegistryUrlConfig>("registry") {
798 workspace_config.registry = found;
799 } else if let Ok(found) = config.get::<WorkspaceRegistryUrlConfig>("registry_urls") {
800 workspace_config.registry = found;
801 } else if let Ok(found) = config.get::<WorkspaceRegistryUrlConfig>("registryUrls") {
802 workspace_config.registry = found;
803 }
804 if let Ok(found) = config.get::<WorkspaceDirectoriesConfig>("directories") {
805 workspace_config.directories = found;
806 }
807 if let Ok(found) = config.get_string("package_manager") {
808 workspace_config.package_manager = PackageManagerType::from_str(&found).unwrap();
809 }
810
811 Ok(workspace_config)
812 }
813 Err(_) => {
814 return Err(ConfigError::NotFound(format!(
815 "{}/package.json",
816 workspace_root.to_string_lossy()
817 )));
818 }
819 }
820 }
821
822 pub fn get_extension(&self, name: &str) -> Option<HashMap<String, Value>> {
823 if let Some(existing) = self.extensions.borrow().get(name) {
824 return Some(existing.clone());
825 }
826
827 let extension = self.config.as_ref().expect("Config value must be determined").get_table(name);
828 match extension.is_ok() {
829 true => {
830 self.extensions.borrow_mut().insert(name.to_string(), extension.ok().unwrap());
831 return self.extensions.borrow().get(name).cloned();
832 }
833 false => None,
834 }
835 }
836}
837
838impl Default for WorkspaceConfig {
839 fn default() -> Self {
840 WorkspaceConfig {
841 schema: "https://stormsoftware.com/schemas/storm-workspace.json".to_string(),
842 config: None,
843 config_file: None,
844 extends: None,
845 workspace_root: get_workspace_root().unwrap().to_str().unwrap().to_string(),
846 mode: WorkspaceMode::Production,
847 variant: WorkspaceVariant::Monorepo,
848 name: "storm-monorepo".to_string(),
849 namespace: "storm-software".to_string(),
850 organization: WorkspaceOrganizationConfig::default(),
851 repository: "https://github.com/storm-software/storm-monorepo".to_string(),
852 license: "Apache-2.0".to_string(),
853 homepage: "https://stormsoftware.com".to_string(),
854 branch: "main".to_string(),
855 preid: None,
856 docs: None,
857 portal: None,
858 licensing: None,
859 contact: None,
860 support: None,
861 release: WorkspaceReleaseConfig::default(),
862 socials: WorkspaceSocialsConfig::default(),
863 error: WorkspaceErrorConfig::default(),
864 directories: WorkspaceDirectoriesConfig::default(),
865 owner: "@storm-software/admin".to_string(),
866 bot: WorkspaceBotConfig::default(),
867 log_level: LogLevel::Info,
868 skip_config_logging: true,
869 skip_cache: false,
870 package_manager: PackageManagerType::Npm,
871 registry: WorkspaceRegistryUrlConfig::default(),
872 timezone: "America/New_York".to_string(),
873 locale: "en-US".to_string(),
874 colors: WorkspaceColorsConfig::default(),
875 extensions: HashMap::new().into(),
876 }
877 }
878}
879
880impl FromStr for WorkspaceConfig {
881 type Err = ();
882
883 fn from_str(input: &str) -> Result<WorkspaceConfig, Self::Err> {
884 let workspace_root = Path::new(input);
885 WorkspaceConfig::from_workspace_root(workspace_root).map_err(|_| ())
886 }
887}