1use thiserror::Error;
8
9#[derive(Error, Debug)]
11pub enum NapError {
12 #[error("invalid NAP URI '{uri}': {reason}")]
14 InvalidUri { uri: String, reason: String },
15
16 #[error("manifest not found: {0}")]
18 ManifestNotFound(String),
19
20 #[error("manifest parse error for '{path}': {source}")]
21 ManifestParseError {
22 path: String,
23 source: serde_yaml::Error,
24 },
25
26 #[error("manifest validation error: {0}")]
27 ManifestValidationError(String),
28
29 #[error("manifest write error for '{path}': {source}")]
30 ManifestWriteError {
31 path: String,
32 source: std::io::Error,
33 },
34
35 #[error("query path not found: '{path}' in manifest '{manifest_id}'")]
37 QueryPathNotFound { path: String, manifest_id: String },
38
39 #[error("invalid query path: '{0}'")]
40 InvalidQueryPath(String),
41
42 #[error("repository not found at '{0}'")]
44 RepositoryNotFound(String),
45
46 #[error(
47 "operation requires a local NAP working tree for '{repository}'; use 'nap pull {repository}' first"
48 )]
49 LocalWorkingTreeRequired { repository: String },
50
51 #[error("repository already exists at '{0}'")]
52 RepositoryAlreadyExists(String),
53
54 #[error("entity type not found: '{0}'")]
56 EntityTypeNotFound(String),
57
58 #[error("VCS error: {0}")]
60 VcsError(String),
61
62 #[error("ref not found: '{0}'")]
63 RefNotFound(String),
64
65 #[error(
67 "cannot {operation}: no version-control backend is configured. \
68 Filesystem state is preserved, but history/sync is unavailable. \
69 Configure one with 'nap backend configure'."
70 )]
71 BackendNotConfigured { operation: String },
72
73 #[error("version-control backend is unavailable: {message}")]
74 BackendUnavailable { message: String },
75
76 #[error("version-control backend operation failed ({operation}): {message}")]
77 BackendOperationFailed { operation: String, message: String },
78
79 #[error("content hash mismatch: expected {expected}, got {actual}")]
81 ContentHashMismatch { expected: String, actual: String },
82
83 #[error("I/O error: {0}")]
85 Io(#[from] std::io::Error),
86
87 #[error("merge conflict at '{path}': {details}")]
89 MergeConflict { path: String, details: String },
90
91 #[error("SDL parse error: {0}")]
92 SdlParseError(String),
93
94 #[error("SDL validation error: {reason}")]
95 SdlValidationError { reason: String },
96
97 #[error("merge strategy error at '{path}': {reason}")]
98 MergeStrategyError { path: String, reason: String },
99
100 #[error("merge validation error: {reason}")]
101 MergeValidationError { reason: String },
102
103 #[error("no branch or commit specified and no default_branch configured. ")]
105 NoDefaultBranch,
106
107 #[error("unable to resolve resource '{address}': {message}")]
108 ResolutionFailed { address: String, message: String },
109
110 #[error("permission denied: {0}")]
112 PermissionDenied(String),
113
114 #[error("gRPC error: {0}")]
116 GrpcError(String),
117
118 #[error("{0}")]
120 Other(String),
121}
122
123pub type NapResult<T> = Result<T, NapError>;