@@ -15,9 +15,7 @@ pub mod catalog;
1515pub mod complex_semver;
1616pub mod exact;
1717pub mod file;
18- #[ cfg( test) ]
19- #[ path = "specifier/get_alias_name_test.rs" ]
20- mod get_alias_name_test;
18+
2119#[ cfg( test) ]
2220#[ path = "specifier/get_node_range_test.rs" ]
2321mod get_node_range_test;
@@ -31,21 +29,11 @@ mod has_same_release_channel_as_test;
3129#[ cfg( test) ]
3230#[ path = "specifier/has_same_version_number_as_test.rs" ]
3331mod has_same_version_number_as_test;
34- #[ cfg( test) ]
35- #[ path = "specifier/has_semver_range_of_test.rs" ]
36- mod has_semver_range_of_test;
32+
3733#[ cfg( test) ]
3834#[ path = "specifier/is_eligible_update_for_test.rs" ]
3935mod is_eligible_update_for_test;
40- #[ cfg( test) ]
41- #[ path = "specifier/is_older_than_by_minor_test.rs" ]
42- mod is_older_than_by_minor_test;
43- #[ cfg( test) ]
44- #[ path = "specifier/is_older_than_by_patch_test.rs" ]
45- mod is_older_than_by_patch_test;
46- #[ cfg( test) ]
47- #[ path = "specifier/is_older_than_test.rs" ]
48- mod is_older_than_test;
36+
4937pub mod latest;
5038pub mod major;
5139pub mod minor;
@@ -60,15 +48,11 @@ pub mod range;
6048pub mod range_major;
6149pub mod range_minor;
6250pub mod regexes;
63- #[ cfg( test) ]
64- #[ path = "specifier/resolve_workspace_protocol_test.rs" ]
65- mod resolve_workspace_protocol_test;
51+
6652#[ cfg( test) ]
6753#[ path = "specifier/satisfies_all_test.rs" ]
6854mod satisfies_all_test;
69- #[ cfg( test) ]
70- #[ path = "specifier/satisfies_test.rs" ]
71- mod satisfies_test;
55+
7256pub mod tag;
7357pub mod url;
7458#[ cfg( test) ]
@@ -78,13 +62,8 @@ mod with_node_version_test;
7862#[ path = "specifier/with_range_test.rs" ]
7963mod with_range_test;
8064pub mod workspace_protocol;
81- #[ cfg( test) ]
82- #[ path = "specifier/workspace_protocol_test.rs" ]
83- mod workspace_protocol_test;
65+
8466pub mod workspace_specifier;
85- #[ cfg( test) ]
86- #[ path = "specifier/workspace_specifier_test.rs" ]
87- mod workspace_specifier_test;
8867
8968thread_local ! {
9069 static SPECIFIER_CACHE : RefCell <HashMap <String , Rc <Specifier >>> = RefCell :: new( HashMap :: new( ) ) ;
@@ -126,11 +105,6 @@ pub fn strip_semver_range(value: &str) -> &str {
126105 . unwrap_or ( value)
127106}
128107
129- /// Remove workspace: from the start of a specifier
130- fn strip_workspace_protocol ( value : & str ) -> & str {
131- value. strip_prefix ( "workspace:" ) . unwrap_or ( value)
132- }
133-
134108#[ derive( Debug , PartialEq ) ]
135109pub enum Specifier {
136110 Alias ( alias:: Alias ) , // "npm:foo@1.2.3"
@@ -202,11 +176,6 @@ impl Specifier {
202176 } )
203177 }
204178
205- /// Check if the given version string is a valid semver version
206- pub fn is_valid_semver ( value : & str ) -> bool {
207- Self :: new_node_range ( value) . is_some ( )
208- }
209-
210179 /// Create a new Specifier for the given version string
211180 pub ( crate ) fn create ( value : & str ) -> Self {
212181 if value. is_empty ( ) {
@@ -292,20 +261,6 @@ impl Specifier {
292261 }
293262 }
294263
295- /// If the current variant is a Specifier::Alias, returns the name of the npm
296- /// dependency which is being aliased.
297- ///
298- /// Examples:
299- /// - "npm:lodash@^4.17.21" -> Some("lodash")
300- /// - "^16.11.10" -> None
301- /// - "npm:express" -> None
302- pub fn get_alias_name ( & self ) -> Option < & str > {
303- match self {
304- Self :: Alias ( alias) => Some ( & alias. name ) ,
305- _ => None ,
306- }
307- }
308-
309264 /// Returns the semver version number of the specifier, if it exists. Only the
310265 /// version number is returned, WITHOUT semver range characters.
311266 ///
@@ -755,38 +710,6 @@ impl Specifier {
755710 }
756711 }
757712
758- /// Check if this specifier uses the given semver range type.
759- ///
760- /// Examples:
761- /// - "^1.2.3" with SemverRange::Minor → true
762- /// - "~1.2.3" with SemverRange::Minor → false
763- /// - "1.2.3" with SemverRange::Exact → true
764- pub fn has_semver_range_of ( & self , range : & SemverRange ) -> bool {
765- match self {
766- // Exact variants (no range prefix) → SemverRange::Exact
767- Self :: Exact ( _) | Self :: Major ( _) | Self :: Minor ( _) => range == & SemverRange :: Exact ,
768-
769- // Range variants with explicit semver_range field
770- Self :: Range ( s) => & s. semver_range == range,
771- Self :: RangeMajor ( s) => & s. semver_range == range,
772- Self :: RangeMinor ( s) => & s. semver_range == range,
773-
774- // Variants that may contain a semver_range (Option)
775- Self :: Alias ( s) => s. inner_specifier . get_semver_range ( ) . as_ref ( ) == Some ( range) ,
776- Self :: Git ( s) => s. semver_range . as_ref ( ) == Some ( range) ,
777- Self :: WorkspaceProtocol ( s) => match & s. inner_specifier {
778- workspace_specifier:: WorkspaceSpecifier :: RangeOnly ( r) => r == range,
779- workspace_specifier:: WorkspaceSpecifier :: Resolved ( spec) => spec. get_semver_range ( ) . as_ref ( ) == Some ( range) ,
780- } ,
781-
782- // Latest("*") maps to SemverRange::Any
783- Self :: Latest ( s) => s. raw == "*" && range == & SemverRange :: Any ,
784-
785- // All other variants have no semver range
786- Self :: Catalog ( _) | Self :: ComplexSemver ( _) | Self :: File ( _) | Self :: None | Self :: Tag ( _) | Self :: Unsupported ( _) | Self :: Url ( _) => false ,
787- }
788- }
789-
790713 /// Is this specifier eligible to update the given specifier based on the
791714 /// given target constraint?
792715 ///
@@ -824,58 +747,6 @@ impl Specifier {
824747 }
825748 }
826749
827- /// Check if this specifier represents an older version than the other.
828- ///
829- /// Examples:
830- /// - "1.0.0" compared to "2.0.0" → true
831- /// - "2.0.0" compared to "1.0.0" → false
832- /// - "1.0.0" compared to "1.0.0" → false
833- pub fn is_older_than ( & self , other : & Self ) -> bool {
834- if !self . has_comparable_version ( ) || !other. has_comparable_version ( ) {
835- return false ;
836- }
837- match ( self . get_node_version ( ) , other. get_node_version ( ) ) {
838- ( Some ( self_version) , Some ( other_version) ) => self_version < other_version,
839- _ => false ,
840- }
841- }
842-
843- /// Is this specifier on the same major version, but otherwise older?
844- ///
845- /// Examples:
846- /// - "1.0.0" compared to "1.1.0" → true
847- /// - "1.0.1" compared to "1.1.0" → true
848- /// - "1.0.0" compared to "2.0.0" → false
849- /// - "1.1.0" compared to "1.0.0" → false
850- pub fn is_older_than_by_minor ( & self , other : & Self ) -> bool {
851- if !self . has_comparable_version ( ) || !other. has_comparable_version ( ) {
852- return false ;
853- }
854- match ( self . get_node_version ( ) , other. get_node_version ( ) ) {
855- ( Some ( self_version) , Some ( other_version) ) => self_version. major == other_version. major && self_version < other_version,
856- _ => false ,
857- }
858- }
859-
860- /// Is this specifier on the same major and minor version, but otherwise
861- /// older?
862- ///
863- /// Examples:
864- /// - "1.0.0" compared to "1.0.1" → true
865- /// - "1.0.0" compared to "1.1.0" → false
866- /// - "1.0.1" compared to "1.0.0" → false
867- pub fn is_older_than_by_patch ( & self , other : & Self ) -> bool {
868- if !self . has_comparable_version ( ) || !other. has_comparable_version ( ) {
869- return false ;
870- }
871- match ( self . get_node_version ( ) , other. get_node_version ( ) ) {
872- ( Some ( self_version) , Some ( other_version) ) => {
873- self_version. major == other_version. major && self_version. minor == other_version. minor && self_version < other_version
874- }
875- _ => false ,
876- }
877- }
878-
879750 /// Check if this specifier uses the workspace protocol.
880751 ///
881752 /// Examples:
@@ -891,34 +762,6 @@ impl Specifier {
891762 matches ! ( self , Self :: Catalog ( _) )
892763 }
893764
894- /// Does this specifier match the given range?
895- ///
896- /// Examples:
897- /// - "1.2.3" satisfies Range("^1.0.0") → true
898- /// - "2.0.0" satisfies Range("^1.0.0") → false
899- /// - "0.9.0" satisfies Range("^1.0.0") → false
900- pub fn satisfies ( & self , range : & node_semver:: Range ) -> bool {
901- // Workspace protocols with embedded versions should return false
902- // because they need to be resolved first
903- if matches ! ( self , Self :: WorkspaceProtocol ( _) ) {
904- return false ;
905- }
906-
907- // Try to get a node_range from self for range-to-range comparison
908- // Use allows_any to check if self's range overlaps with target range
909- if let Some ( self_range) = self . get_node_range ( ) {
910- return self_range. allows_any ( range) ;
911- }
912-
913- // If self has a version (not a range), check if it satisfies the target range
914- if let Some ( self_version) = self . get_node_version ( ) {
915- return range. satisfies ( & self_version) ;
916- }
917-
918- // No version or range to compare
919- false
920- }
921-
922765 /// Check if this specifier satisfies all other specifiers.
923766 ///
924767 /// Handles both:
@@ -962,74 +805,6 @@ impl Specifier {
962805 }
963806 }
964807 }
965-
966- /// Resolve a workspace protocol specifier using the given local version.
967- ///
968- /// If the specifier is a workspace protocol (e.g., "workspace:^"), this
969- /// method combines the protocol with the local version to produce a regular
970- /// specifier (e.g., "^1.2.3").
971- ///
972- /// If the specifier is not a workspace protocol, it returns itself unchanged
973- /// (the same cached Rc).
974- ///
975- /// Examples:
976- /// - "workspace:^" + Exact("1.2.3") → "^1.2.3"
977- /// - "workspace:~" + Exact("1.2.3") → "~1.2.3"
978- /// - "workspace:*" + Exact("1.2.3") → "*"
979- /// - "workspace:^1.2.3" + Exact("2.0.0") → "^1.2.3" (version already embedded)
980- /// - "^1.2.3" + Exact("2.0.0") → "^1.2.3" (not a workspace protocol, returns self)
981- pub fn resolve_workspace_protocol ( & self , local_version : & Self ) -> Option < Rc < Self > > {
982- // Validate that local_version is an Exact variant
983- if !matches ! ( local_version, Self :: Exact ( _) ) {
984- return None ;
985- }
986-
987- // If not a workspace protocol, return self unchanged by looking it up in cache
988- let Self :: WorkspaceProtocol ( ws) = self else {
989- let raw = match self {
990- Self :: Alias ( a) => & a. raw ,
991- Self :: Catalog ( c) => & c. raw ,
992- Self :: ComplexSemver ( s) => & s. raw ,
993- Self :: Exact ( e) => & e. raw ,
994- Self :: File ( f) => & f. raw ,
995- Self :: Git ( g) => & g. raw ,
996- Self :: Latest ( l) => & l. raw ,
997- Self :: Major ( m) => & m. raw ,
998- Self :: Minor ( m) => & m. raw ,
999- Self :: Range ( r) => & r. raw ,
1000- Self :: RangeMajor ( r) => & r. raw ,
1001- Self :: RangeMinor ( r) => & r. raw ,
1002- Self :: Tag ( t) => & t. raw ,
1003- Self :: Url ( u) => & u. raw ,
1004- Self :: Unsupported ( u) => u,
1005- Self :: None => "" ,
1006- Self :: WorkspaceProtocol ( w) => & w. raw ,
1007- } ;
1008- return Some ( Self :: new ( raw) ) ;
1009- } ;
1010-
1011- // If workspace protocol has resolved specifier, strip "workspace:" and create new specifier
1012- if ws. as_resolved ( ) . is_some ( ) {
1013- let resolved_str = strip_workspace_protocol ( & ws. raw ) ;
1014- return Some ( Self :: new ( resolved_str) ) ;
1015- }
1016-
1017- // Otherwise, combine the semver range with local_version's number
1018- let local_number = local_version. get_semver_number ( ) . expect ( "Exact should have semver_number" ) ;
1019-
1020- // Get the range/operator from workspace protocol
1021- let range_or_op = strip_workspace_protocol ( & ws. raw ) ;
1022-
1023- // Handle special case: "*" stays as "*"
1024- if range_or_op == "*" {
1025- return Some ( Self :: new ( "*" ) ) ;
1026- }
1027-
1028- // Combine operator/range character with local version number
1029- // For multi-char operators like >=, >, <=, < this preserves them correctly
1030- let resolved_str = format ! ( "{range_or_op}{local_number}" ) ;
1031- Some ( Self :: new ( & resolved_str) )
1032- }
1033808}
1034809
1035810// =============================================================================
0 commit comments