1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::error::extension::LoadExtensionManifestError;
use crate::error::fs::{
    CanonicalizePathError, CreateDirAllError, EnsureDirExistsError, NoParentPathError,
};
use crate::error::get_user_home::GetUserHomeError;
use handlebars::RenderError;
use std::path::PathBuf;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ConfigError {
    #[error("failed to ensure config directory exists")]
    EnsureConfigDirectoryExistsFailed(#[source] EnsureDirExistsError),

    #[error("Failed to determine config directory path")]
    DetermineConfigDirectoryFailed(#[source] GetUserHomeError),

    #[error("Failed to determine shared network data directory")]
    DetermineSharedNetworkDirectoryFailed(#[source] GetUserHomeError),
}

#[derive(Error, Debug)]
pub enum GetOutputEnvFileError {
    #[error("failed to canonicalize output_env_file")]
    CanonicalizePath(#[from] CanonicalizePathError),

    #[error("The output_env_file must be within the project root, but is {}", .0.display())]
    OutputEnvFileMustBeInProjectRoot(PathBuf),

    #[error("The output_env_file must be a relative path, but is {}", .0.display())]
    OutputEnvFileMustBeRelative(PathBuf),

    #[error(transparent)]
    NoParentPath(#[from] NoParentPathError),
}

#[derive(Error, Debug)]
pub enum GetTempPathError {
    #[error(transparent)]
    CreateDirAll(#[from] CreateDirAllError),
}

#[derive(Error, Debug)]
#[error("failed to render field '{field}' with value '{value}'")]
pub struct RenderErrorWithContext {
    pub field: String,
    pub value: String,
    pub source: RenderError,
}

#[derive(Error, Debug)]
#[error("failed to apply extension canister type '{extension}' to canister '{canister}'")]
pub struct ApplyExtensionCanisterTypeErrorWithContext {
    pub canister: Box<String>,
    pub extension: Box<String>,
    pub source: ApplyExtensionCanisterTypeError,
}

#[derive(Error, Debug)]
pub enum ApplyExtensionCanisterTypesError {
    #[error("the canisters field in dfx.json must be an object")]
    CanistersFieldIsNotAnObject(),

    #[error("canister '{0}' in dfx.json must be an object")]
    CanisterIsNotAnObject(String),

    #[error(transparent)]
    ApplyExtensionCanisterType(#[from] ApplyExtensionCanisterTypeError),
}

#[derive(Error, Debug)]
pub enum ApplyExtensionCanisterTypeError {
    #[error("failed to apply defaults from extension '{extension}' to canister '{canister}'")]
    ApplyDefaults {
        canister: Box<String>,
        extension: Box<String>,
        source: ApplyExtensionCanisterTypeDefaultsError,
    },

    #[error("canister '{canister}' has unknown type '{extension}' and there is no installed extension by that name which could define it")]
    NoExtensionForUnknownCanisterType { canister: String, extension: String },

    #[error(transparent)]
    LoadExtensionManifest(LoadExtensionManifestError),

    #[error("canister '{canister}' has type '{extension}', but that extension does not define a canister type")]
    ExtensionDoesNotDefineCanisterType { canister: String, extension: String },
}

#[derive(Error, Debug)]
pub enum ApplyExtensionCanisterTypeDefaultsError {
    #[error(transparent)]
    AppendMetadata(#[from] AppendMetadataError),

    #[error(transparent)]
    MergeTechStackError(#[from] MergeTechStackError),

    #[error(transparent)]
    Render(Box<RenderErrorWithContext>),
}

#[derive(Error, Debug)]
pub enum AppendMetadataError {
    #[error("expected canister metadata to be an array")]
    ExpectedCanisterMetadataArray,

    #[error("expected extension canister type metadata to be an array")]
    ExpectedExtensionCanisterTypeMetadataArray,
}

#[derive(Error, Debug)]
pub enum MergeTechStackError {
    #[error("expected canister tech_stack to be an object")]
    ExpectedCanisterTechStackObject,

    #[error("expected extension canister type tech_stack to be an object")]
    ExpectedExtensionCanisterTypeTechStackObject,
}