Skip to main content

moon_pdk_api/toolchain/
tier2.rs

1use crate::context::*;
2use crate::host::*;
3use crate::is_false;
4use moon_config::{UnresolvedVersionSpec, Version, VersionSpec};
5use moon_project::ProjectFragment;
6use moon_task::TaskFragment;
7use std::collections::BTreeMap;
8use std::path::PathBuf;
9use warpgate_api::{VirtualPath, api_enum, api_struct};
10
11api_struct!(
12    /// Input passed to the `define_requirements` function.
13    pub struct DefineRequirementsInput {
14        /// Current moon context.
15        pub context: MoonContext,
16
17        /// Workspace toolchain configuration.
18        pub toolchain_config: serde_json::Value,
19    }
20);
21
22api_struct!(
23    /// Output returned from the `define_requirements` function.
24    #[serde(default)]
25    pub struct DefineRequirementsOutput {
26        /// Other toolchains that this toolchain requires and must be setup before hand.
27        /// If targeting an unstable toolchain, the identifier must be prefixed with "unstable_".
28        /// When the toolchain is stable, both identifiers will continue to work.
29        #[serde(skip_serializing_if = "Vec::is_empty")]
30        pub requires: Vec<String>,
31    }
32);
33
34api_struct!(
35    /// Input passed to the `setup_environment` function.
36    pub struct SetupEnvironmentInput {
37        /// Current moon context.
38        pub context: MoonContext,
39
40        /// Virtual path to a global executables directory
41        /// for the current toolchain.
42        pub globals_dir: Option<VirtualPath>,
43
44        /// The project if the dependencies and environment root
45        /// are the project root (non-workspace).
46        pub project: Option<ProjectFragment>,
47
48        /// Virtual path to the dependencies root. This is where
49        /// the lockfile and root manifest should exist.
50        pub root: VirtualPath,
51
52        /// Workspace and project merged toolchain configuration,
53        /// with the latter taking precedence.
54        pub toolchain_config: serde_json::Value,
55    }
56);
57
58api_struct!(
59    /// Output returned from the `setup_environment` function.
60    #[serde(default)]
61    pub struct SetupEnvironmentOutput {
62        /// List of files that have been changed because of this action.
63        #[serde(skip_serializing_if = "Vec::is_empty")]
64        pub changed_files: Vec<PathBuf>,
65
66        /// List of commands to execute during setup.
67        #[serde(skip_serializing_if = "Vec::is_empty")]
68        pub commands: Vec<ExecCommand>,
69
70        /// Operations that were performed. This can be used to track
71        /// metadata like time taken, result status, and more.
72        #[serde(skip_serializing_if = "Vec::is_empty")]
73        pub operations: Vec<Operation>,
74    }
75);
76
77api_struct!(
78    /// Input passed to the `locate_dependencies_root` function.
79    pub struct LocateDependenciesRootInput {
80        /// Current moon context.
81        pub context: MoonContext,
82
83        /// The starting directory in which to locate the root.
84        /// This is typically a project root.
85        pub starting_dir: VirtualPath,
86
87        /// Workspace and project merged toolchain configuration,
88        /// with the latter taking precedence.
89        pub toolchain_config: serde_json::Value,
90    }
91);
92
93api_struct!(
94    /// Output returned from the `locate_dependencies_root` function.
95    #[serde(default)]
96    pub struct LocateDependenciesRootOutput {
97        /// A list of relative globs for all members (packages, libs, etc)
98        /// within the current dependencies workspace. If not defined,
99        /// the current project is the root, or there is no workspace.
100        #[serde(skip_serializing_if = "Option::is_none")]
101        pub members: Option<Vec<String>>,
102
103        /// Virtual path to the located root. If no root was found,
104        /// return `None` to abort any relevant operations.
105        #[serde(skip_serializing_if = "Option::is_none")]
106        pub root: Option<PathBuf>,
107    }
108);
109
110api_struct!(
111    /// Input passed to the `install_dependencies` function.
112    /// Requires `locate_dependencies_root`.
113    pub struct InstallDependenciesInput {
114        /// Current moon context.
115        pub context: MoonContext,
116
117        /// List of packages to only install dependencies for.
118        pub packages: Vec<String>,
119
120        /// Only install production dependencies.
121        pub production: bool,
122
123        /// The project if the dependencies and environment root
124        /// are the project root (non-workspace).
125        pub project: Option<ProjectFragment>,
126
127        /// Virtual path to the dependencies root. This is where
128        /// the lockfile and root manifest should exist.
129        pub root: VirtualPath,
130
131        /// Workspace and project merged toolchain configuration,
132        /// with the latter taking precedence.
133        pub toolchain_config: serde_json::Value,
134    }
135);
136
137api_struct!(
138    /// Output returned from the `install_dependencies` function.
139    #[serde(default)]
140    pub struct InstallDependenciesOutput {
141        /// The command to run in the dependencies root to dedupe
142        /// dependencies. If not defined, will not dedupe.
143        #[serde(skip_serializing_if = "Option::is_none")]
144        pub dedupe_command: Option<ExecCommand>,
145
146        /// The command to run in the dependencies root to install
147        /// dependencies. If not defined, will not install.
148        #[serde(skip_serializing_if = "Option::is_none")]
149        pub install_command: Option<ExecCommand>,
150
151        /// Operations that were performed. This can be used to track
152        /// metadata like time taken, result status, and more.
153        #[serde(skip_serializing_if = "Vec::is_empty")]
154        pub operations: Vec<Operation>,
155    }
156);
157
158api_struct!(
159    /// Input passed to the `parse_manifest` function.
160    pub struct ParseManifestInput {
161        /// Current moon context.
162        pub context: MoonContext,
163
164        /// Virtual path to the manifest file.
165        pub path: VirtualPath,
166
167        /// Virtual path to the dependencies root. This is where
168        /// the lockfile and root manifest should exist.
169        pub root: VirtualPath,
170    }
171);
172
173api_struct!(
174    /// Output returned from the `parse_manifest` function.
175    #[serde(default)]
176    pub struct ParseManifestOutput {
177        /// Build dependencies.
178        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
179        pub build_dependencies: BTreeMap<String, ManifestDependency>,
180
181        /// Development dependencies.
182        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
183        pub dev_dependencies: BTreeMap<String, ManifestDependency>,
184
185        /// Production dependencies.
186        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
187        pub dependencies: BTreeMap<String, ManifestDependency>,
188
189        /// Peer dependencies.
190        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
191        pub peer_dependencies: BTreeMap<String, ManifestDependency>,
192
193        /// Can the package be published or not.
194        #[serde(skip_serializing_if = "is_false")]
195        pub publishable: bool,
196
197        /// Current version of the package.
198        #[serde(skip_serializing_if = "Option::is_none")]
199        pub version: Option<Version>,
200    }
201);
202
203api_struct!(
204    /// Represents a dependency in a manifest file.
205    #[serde(default)]
206    pub struct ManifestDependencyConfig {
207        /// The version is inherited from the workspace.
208        #[serde(skip_serializing_if = "is_false")]
209        pub inherited: bool,
210
211        /// List of features enabled for this dependency.
212        #[serde(skip_serializing_if = "Vec::is_empty")]
213        pub features: Vec<String>,
214
215        /// Relative path to the dependency on the local file system.
216        #[serde(skip_serializing_if = "Option::is_none")]
217        pub path: Option<PathBuf>,
218
219        /// Unique reference, identifier, or specifier.
220        #[serde(skip_serializing_if = "Option::is_none")]
221        pub reference: Option<String>,
222
223        /// URL of the remote dependency.
224        #[serde(skip_serializing_if = "Option::is_none")]
225        pub url: Option<String>,
226
227        /// The defined version or requirement.
228        #[serde(skip_serializing_if = "Option::is_none")]
229        pub version: Option<UnresolvedVersionSpec>,
230    }
231);
232
233api_enum!(
234    /// Represents a dependency definition in a manifest file.
235    #[serde(untagged)]
236    pub enum ManifestDependency {
237        /// Inherited from workspace.
238        Inherited(bool),
239
240        /// Only a version.
241        Version(UnresolvedVersionSpec),
242
243        /// Full configuration.
244        Config(ManifestDependencyConfig),
245    }
246);
247
248impl ManifestDependency {
249    /// Defines an explicit version or requirement.
250    pub fn new(version: UnresolvedVersionSpec) -> Self {
251        Self::Version(version)
252    }
253
254    /// Inherits a version from the workspace.
255    pub fn inherited() -> Self {
256        Self::Inherited(true)
257    }
258
259    /// Defines an explicit local path.
260    pub fn path(path: PathBuf) -> Self {
261        Self::Config(ManifestDependencyConfig {
262            path: Some(path),
263            ..Default::default()
264        })
265    }
266
267    /// Defines an explicit remote URL.
268    pub fn url(url: String) -> Self {
269        Self::Config(ManifestDependencyConfig {
270            url: Some(url),
271            ..Default::default()
272        })
273    }
274
275    /// Return an applicable version.
276    pub fn get_version(&self) -> Option<&UnresolvedVersionSpec> {
277        match self {
278            ManifestDependency::Version(version) => Some(version),
279            ManifestDependency::Config(cfg) => cfg.version.as_ref(),
280            _ => None,
281        }
282    }
283
284    /// Is the dependency version inherited.
285    pub fn is_inherited(&self) -> bool {
286        match self {
287            ManifestDependency::Inherited(state) => *state,
288            ManifestDependency::Config(cfg) => cfg.inherited,
289            _ => false,
290        }
291    }
292}
293
294api_struct!(
295    /// Input passed to the `parse_lock` function.
296    pub struct ParseLockInput {
297        /// Current moon context.
298        pub context: MoonContext,
299
300        /// Virtual path to the lockfile.
301        pub path: VirtualPath,
302
303        /// Virtual path to the dependencies root. This is where
304        /// the lockfile and root manifest should exist.
305        pub root: VirtualPath,
306    }
307);
308
309api_struct!(
310    /// Output returned from the `parse_lock` function.
311    #[serde(default)]
312    pub struct ParseLockOutput {
313        /// Map of all dependencies and their locked versions.
314        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
315        pub dependencies: BTreeMap<String, Vec<LockDependency>>,
316    }
317);
318
319api_struct!(
320    /// Represents a dependency definition in a lockfile.
321    #[serde(default)]
322    pub struct LockDependency {
323        /// A unique hash: checksum, integrity, etc.
324        #[serde(skip_serializing_if = "Option::is_none")]
325        pub hash: Option<String>,
326
327        /// General metadata.
328        #[serde(skip_serializing_if = "Option::is_none")]
329        pub meta: Option<String>,
330
331        /// The version requirement.
332        #[serde(skip_serializing_if = "Option::is_none")]
333        pub req: Option<UnresolvedVersionSpec>,
334
335        /// The resolved version.
336        #[serde(skip_serializing_if = "Option::is_none")]
337        pub version: Option<VersionSpec>,
338    }
339);
340
341api_struct!(
342    /// Input passed to the `hash_task_contents` function.
343    pub struct HashTaskContentsInput {
344        /// Current moon context.
345        pub context: MoonContext,
346
347        /// Fragment of the project that the task belongs to.
348        pub project: ProjectFragment,
349
350        /// Fragment of the task being hashed.
351        pub task: TaskFragment,
352
353        /// Workspace and project merged toolchain configuration,
354        /// with the latter taking precedence.
355        pub toolchain_config: serde_json::Value,
356    }
357);
358
359api_struct!(
360    /// Output returned from the `hash_task_contents` function.
361    pub struct HashTaskContentsOutput {
362        /// Contents that should be included during hash generation.
363        pub contents: Vec<serde_json::Value>,
364    }
365);