diff --git a/src/cli/init.rs b/src/cli/init.rs index 6036fa6..561a41c 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -4,8 +4,7 @@ use clap::Args; use colored::Colorize; use inquire::validator::Validation; use pesde::{ - errors::ManifestReadError, manifest::ScriptName, names::PackageName, Project, - DEFAULT_INDEX_NAME, + errors::ManifestReadError, names::PackageName, scripts::ScriptName, Project, DEFAULT_INDEX_NAME, }; use std::{path::Path, str::FromStr}; diff --git a/src/cli/install.rs b/src/cli/install.rs index 1f28be3..91af59f 100644 --- a/src/cli/install.rs +++ b/src/cli/install.rs @@ -2,7 +2,7 @@ use crate::cli::{reqwest_client, IsUpToDate}; use anyhow::Context; use clap::Args; use indicatif::MultiProgress; -use pesde::{lockfile::Lockfile, manifest::TargetKind, Project}; +use pesde::{lockfile::Lockfile, manifest::target::TargetKind, Project}; use std::{collections::HashSet, sync::Arc, time::Duration}; #[derive(Debug, Args)] diff --git a/src/cli/publish.rs b/src/cli/publish.rs index c9097c6..99b8980 100644 --- a/src/cli/publish.rs +++ b/src/cli/publish.rs @@ -1,7 +1,7 @@ use anyhow::Context; use clap::Args; use colored::Colorize; -use pesde::{manifest::Target, Project, MANIFEST_FILE_NAME, MAX_ARCHIVE_SIZE}; +use pesde::{manifest::target::Target, Project, MANIFEST_FILE_NAME, MAX_ARCHIVE_SIZE}; use std::path::Component; #[derive(Debug, Args)] diff --git a/src/linking/generator.rs b/src/linking/generator.rs index e84f466..2f2ed27 100644 --- a/src/linking/generator.rs +++ b/src/linking/generator.rs @@ -2,7 +2,7 @@ use std::path::{Component, Path}; use full_moon::{ast::luau::ExportedTypeDeclaration, visitors::Visitor}; -use crate::manifest::Target; +use crate::manifest::target::Target; struct TypeVisitor { types: Vec, diff --git a/src/linking/mod.rs b/src/linking/mod.rs index 5996343..d5685d3 100644 --- a/src/linking/mod.rs +++ b/src/linking/mod.rs @@ -1,9 +1,9 @@ use crate::{ linking::generator::get_file_types, lockfile::DownloadedGraph, - manifest::{ScriptName, Target}, + manifest::target::Target, names::PackageNames, - scripts::execute_script, + scripts::{execute_script, ScriptName}, source::{PackageRef, VersionId}, Project, PACKAGES_CONTAINER_NAME, }; diff --git a/src/lockfile.rs b/src/lockfile.rs index ceef7db..0cf02ff 100644 --- a/src/lockfile.rs +++ b/src/lockfile.rs @@ -1,5 +1,9 @@ use crate::{ - manifest::{DependencyType, OverrideKey, Target, TargetKind}, + manifest::{ + overrides::OverrideKey, + target::{Target, TargetKind}, + DependencyType, + }, names::{PackageName, PackageNames}, source::{DependencySpecifiers, PackageRef, PackageRefs, VersionId}, }; diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs new file mode 100644 index 0000000..56c4dc8 --- /dev/null +++ b/src/manifest/mod.rs @@ -0,0 +1,96 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use relative_path::RelativePathBuf; +use semver::Version; +use serde::{Deserialize, Serialize}; + +use crate::{ + manifest::{overrides::OverrideKey, target::Target}, + names::{PackageName, PackageNames}, + source::{DependencySpecifiers, VersionId}, +}; + +pub mod overrides; +pub mod target; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Manifest { + pub name: PackageName, + pub version: Version, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub description: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub license: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub authors: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub repository: Option, + pub target: Target, + #[serde(default)] + pub private: bool, + #[serde(default, skip_serializing)] + pub scripts: BTreeMap, + #[serde(default)] + pub indices: BTreeMap, + #[cfg(feature = "wally-compat")] + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub wally_indices: BTreeMap, + #[serde(default, skip_serializing)] + pub overrides: BTreeMap, + #[serde(default)] + pub includes: BTreeSet, + #[cfg(feature = "patches")] + #[serde(default, skip_serializing)] + pub patches: BTreeMap>, + + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub dependencies: BTreeMap, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub peer_dependencies: BTreeMap, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub dev_dependencies: BTreeMap, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[serde(rename_all = "snake_case")] +pub enum DependencyType { + Standard, + Dev, + Peer, +} + +impl Manifest { + pub fn all_dependencies( + &self, + ) -> Result< + BTreeMap, + errors::AllDependenciesError, + > { + let mut all_deps = BTreeMap::new(); + + for (deps, ty) in [ + (&self.dependencies, DependencyType::Standard), + (&self.peer_dependencies, DependencyType::Peer), + (&self.dev_dependencies, DependencyType::Dev), + ] { + for (alias, spec) in deps { + if all_deps.insert(alias.clone(), (spec.clone(), ty)).is_some() { + return Err(errors::AllDependenciesError::AliasConflict(alias.clone())); + } + } + } + + Ok(all_deps) + } +} + +pub mod errors { + use thiserror::Error; + + #[derive(Debug, Error)] + #[non_exhaustive] + pub enum AllDependenciesError { + #[error("another specifier is already using the alias {0}")] + AliasConflict(String), + } +} diff --git a/src/manifest/overrides.rs b/src/manifest/overrides.rs new file mode 100644 index 0000000..26c0f41 --- /dev/null +++ b/src/manifest/overrides.rs @@ -0,0 +1,58 @@ +use serde_with::{DeserializeFromStr, SerializeDisplay}; +use std::{ + fmt::{Display, Formatter}, + str::FromStr, +}; + +#[derive( + Debug, DeserializeFromStr, SerializeDisplay, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, +)] +pub struct OverrideKey(pub Vec>); + +impl FromStr for OverrideKey { + type Err = errors::OverrideKeyFromStr; + + fn from_str(s: &str) -> Result { + let overrides = s + .split(',') + .map(|overrides| overrides.split('>').map(|s| s.to_string()).collect()) + .collect::>>(); + + if overrides.is_empty() { + return Err(errors::OverrideKeyFromStr::Empty); + } + + Ok(Self(overrides)) + } +} + +impl Display for OverrideKey { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + self.0 + .iter() + .map(|overrides| { + overrides + .iter() + .map(|o| o.as_str()) + .collect::>() + .join(">") + }) + .collect::>() + .join(",") + ) + } +} + +pub mod errors { + use thiserror::Error; + + #[derive(Debug, Error)] + #[non_exhaustive] + pub enum OverrideKeyFromStr { + #[error("empty override key")] + Empty, + } +} diff --git a/src/manifest.rs b/src/manifest/target.rs similarity index 53% rename from src/manifest.rs rename to src/manifest/target.rs index 18da2ef..e5cb4f9 100644 --- a/src/manifest.rs +++ b/src/manifest/target.rs @@ -1,13 +1,7 @@ -use crate::{ - names::{PackageName, PackageNames}, - source::{DependencySpecifiers, VersionId}, -}; use relative_path::RelativePathBuf; -use semver::Version; use serde::{Deserialize, Serialize}; -use serde_with::{DeserializeFromStr, SerializeDisplay}; use std::{ - collections::{BTreeMap, BTreeSet}, + collections::BTreeSet, fmt::{Display, Formatter}, str::FromStr, }; @@ -176,155 +170,9 @@ impl Display for Target { } } -#[derive( - Debug, DeserializeFromStr, SerializeDisplay, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, -)] -pub struct OverrideKey(pub Vec>); - -impl FromStr for OverrideKey { - type Err = errors::OverrideKeyFromStr; - - fn from_str(s: &str) -> Result { - let overrides = s - .split(',') - .map(|overrides| overrides.split('>').map(|s| s.to_string()).collect()) - .collect::>>(); - - if overrides.is_empty() { - return Err(errors::OverrideKeyFromStr::Empty); - } - - Ok(Self(overrides)) - } -} - -impl Display for OverrideKey { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - self.0 - .iter() - .map(|overrides| { - overrides - .iter() - .map(|o| o.as_str()) - .collect::>() - .join(">") - }) - .collect::>() - .join(",") - ) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum ScriptName { - #[cfg(feature = "roblox")] - RobloxSyncConfigGenerator, - #[cfg(feature = "wally-compat")] - SourcemapGenerator, -} - -impl Display for ScriptName { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - #[cfg(feature = "roblox")] - ScriptName::RobloxSyncConfigGenerator => write!(f, "roblox_sync_config_generator"), - #[cfg(feature = "wally-compat")] - ScriptName::SourcemapGenerator => write!(f, "sourcemap_generator"), - } - } -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Manifest { - pub name: PackageName, - pub version: Version, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub description: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub license: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub authors: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub repository: Option, - pub target: Target, - #[serde(default)] - pub private: bool, - #[serde(default, skip_serializing)] - pub scripts: BTreeMap, - #[serde(default)] - pub indices: BTreeMap, - #[cfg(feature = "wally-compat")] - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub wally_indices: BTreeMap, - #[serde(default, skip_serializing)] - pub overrides: BTreeMap, - #[serde(default)] - pub includes: BTreeSet, - #[cfg(feature = "patches")] - #[serde(default, skip_serializing)] - pub patches: BTreeMap>, - - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub dependencies: BTreeMap, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub peer_dependencies: BTreeMap, - #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] - pub dev_dependencies: BTreeMap, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[serde(rename_all = "snake_case")] -pub enum DependencyType { - Standard, - Dev, - Peer, -} - -impl Manifest { - pub fn all_dependencies( - &self, - ) -> Result< - BTreeMap, - errors::AllDependenciesError, - > { - let mut all_deps = BTreeMap::new(); - - for (deps, ty) in [ - (&self.dependencies, DependencyType::Standard), - (&self.peer_dependencies, DependencyType::Peer), - (&self.dev_dependencies, DependencyType::Dev), - ] { - for (alias, spec) in deps { - if all_deps.insert(alias.clone(), (spec.clone(), ty)).is_some() { - return Err(errors::AllDependenciesError::AliasConflict(alias.clone())); - } - } - } - - Ok(all_deps) - } -} - pub mod errors { use thiserror::Error; - #[derive(Debug, Error)] - #[non_exhaustive] - pub enum OverrideKeyFromStr { - #[error("empty override key")] - Empty, - } - - #[derive(Debug, Error)] - #[non_exhaustive] - pub enum AllDependenciesError { - #[error("another specifier is already using the alias {0}")] - AliasConflict(String), - } - #[derive(Debug, Error)] #[non_exhaustive] pub enum TargetValidatePublishError { diff --git a/src/scripts.rs b/src/scripts.rs index 822ec11..2f811c6 100644 --- a/src/scripts.rs +++ b/src/scripts.rs @@ -6,6 +6,27 @@ use std::{ thread::spawn, }; +use std::fmt::{Display, Formatter}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum ScriptName { + #[cfg(feature = "roblox")] + RobloxSyncConfigGenerator, + #[cfg(feature = "wally-compat")] + SourcemapGenerator, +} + +impl Display for ScriptName { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + #[cfg(feature = "roblox")] + ScriptName::RobloxSyncConfigGenerator => write!(f, "roblox_sync_config_generator"), + #[cfg(feature = "wally-compat")] + ScriptName::SourcemapGenerator => write!(f, "sourcemap_generator"), + } + } +} + pub fn execute_script, S: AsRef, P: AsRef>( script_name: Option<&str>, script_path: &Path, diff --git a/src/source/mod.rs b/src/source/mod.rs index 81fa654..d780424 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -1,5 +1,8 @@ use crate::{ - manifest::{DependencyType, Target, TargetKind}, + manifest::{ + target::{Target, TargetKind}, + DependencyType, + }, names::PackageNames, Project, }; @@ -246,6 +249,6 @@ pub mod errors { Version(#[from] semver::Error), #[error("malformed target")] - Target(#[from] crate::manifest::errors::TargetKindFromStr), + Target(#[from] crate::manifest::target::errors::TargetKindFromStr), } } diff --git a/src/source/pesde/mod.rs b/src/source/pesde/mod.rs index 4583d56..a48258a 100644 --- a/src/source/pesde/mod.rs +++ b/src/source/pesde/mod.rs @@ -7,7 +7,10 @@ use pkg_ref::PesdePackageRef; use specifier::PesdeDependencySpecifier; use crate::{ - manifest::{DependencyType, Target, TargetKind}, + manifest::{ + target::{Target, TargetKind}, + DependencyType, + }, names::{PackageName, PackageNames}, source::{hash, DependencySpecifiers, PackageSource, ResolveResult, VersionId}, util::authenticate_conn, diff --git a/src/source/pesde/pkg_ref.rs b/src/source/pesde/pkg_ref.rs index e07e73b..e5b1008 100644 --- a/src/source/pesde/pkg_ref.rs +++ b/src/source/pesde/pkg_ref.rs @@ -4,7 +4,10 @@ use semver::Version; use serde::{Deserialize, Serialize}; use crate::{ - manifest::{DependencyType, Target, TargetKind}, + manifest::{ + target::{Target, TargetKind}, + DependencyType, + }, names::PackageName, source::{pesde::PesdePackageSource, DependencySpecifiers, PackageRef, PackageSources}, }; diff --git a/src/source/pesde/specifier.rs b/src/source/pesde/specifier.rs index 1940b55..fbbbb0f 100644 --- a/src/source/pesde/specifier.rs +++ b/src/source/pesde/specifier.rs @@ -1,4 +1,4 @@ -use crate::{manifest::TargetKind, names::PackageName, source::DependencySpecifier}; +use crate::{manifest::target::TargetKind, names::PackageName, source::DependencySpecifier}; use semver::VersionReq; use serde::{Deserialize, Serialize}; use std::fmt::Display;