@@ -706,3 +706,256 @@ impl Package {
706706 }
707707 }
708708}
709+
710+ fn get_unallowed_dependents (
711+ packages : & AHashMap < String , Package > ,
712+ package_name : & String ,
713+ dependencies : & Vec < String > ,
714+ ) -> Option < String > {
715+ for deps_package_name in dependencies {
716+ if let Some ( deps_package) = packages. get ( deps_package_name) {
717+ let deps_allowed_dependents = deps_package. bsconfig . allowed_dependents . to_owned ( ) ;
718+ if let Some ( allowed_dependents) = deps_allowed_dependents {
719+ if !allowed_dependents. contains ( package_name) {
720+ return Some ( deps_package_name. to_string ( ) ) ;
721+ }
722+ }
723+ }
724+ }
725+ return None ;
726+ }
727+ #[ derive( Debug , Clone ) ]
728+ struct UnallowedDependency {
729+ bs_deps : Vec < String > ,
730+ pinned_deps : Vec < String > ,
731+ bs_dev_deps : Vec < String > ,
732+ }
733+
734+ pub fn validate_packages_dependencies ( packages : & AHashMap < String , Package > ) -> bool {
735+ let mut detected_unallowed_dependencies: AHashMap < String , UnallowedDependency > = AHashMap :: new ( ) ;
736+
737+ for ( package_name, package) in packages {
738+ let bs_dependencies = & package. bsconfig . bs_dependencies . to_owned ( ) . unwrap_or ( vec ! [ ] ) ;
739+ let pinned_dependencies = & package. bsconfig . pinned_dependencies . to_owned ( ) . unwrap_or ( vec ! [ ] ) ;
740+ let dev_dependencies = & package. bsconfig . bs_dev_dependencies . to_owned ( ) . unwrap_or ( vec ! [ ] ) ;
741+
742+ vec ! [
743+ ( "bs-dependencies" , bs_dependencies) ,
744+ ( "pinned-dependencies" , pinned_dependencies) ,
745+ ( "bs-dev-dependencies" , dev_dependencies) ,
746+ ]
747+ . iter ( )
748+ . for_each ( |( dependency_type, dependencies) | {
749+ if let Some ( unallowed_dependency_name) = get_unallowed_dependents ( packages, package_name, dependencies) {
750+ let empty_unallowed_deps = UnallowedDependency {
751+ bs_deps : vec ! [ ] ,
752+ pinned_deps : vec ! [ ] ,
753+ bs_dev_deps : vec ! [ ] ,
754+ } ;
755+
756+ let unallowed_dependency = detected_unallowed_dependencies. entry ( String :: from ( package_name) ) ;
757+ let value = unallowed_dependency
758+ . or_insert_with ( ||empty_unallowed_deps) ;
759+ match dependency_type {
760+ & "bs-dependencies" => value. bs_deps . push ( String :: from ( unallowed_dependency_name) ) ,
761+ & "pinned-dependencies" => value. pinned_deps . push ( String :: from ( unallowed_dependency_name) ) ,
762+ & "bs-dev-dependencies" => value. bs_dev_deps . push ( String :: from ( unallowed_dependency_name) ) ,
763+ _ => ( ) ,
764+ }
765+
766+ }
767+ } ) ;
768+ }
769+ for ( package_name, unallowed_deps) in detected_unallowed_dependencies. iter ( ) {
770+ println ! (
771+ "\n {}: {} has the following unallowed dependencies:" ,
772+ console:: style( "Error" ) . red( ) ,
773+ console:: style( package_name) . bold( )
774+ ) ;
775+
776+ vec ! [
777+ ( "bs-dependencies" , unallowed_deps. bs_deps. to_owned( ) ) ,
778+ ( "pinned-dependencies" , unallowed_deps. pinned_deps. to_owned( ) ) ,
779+ ( "bs-dev-dependencies" , unallowed_deps. bs_dev_deps. to_owned( ) ) ,
780+ ]
781+ . iter ( )
782+ . for_each ( |( deps_type, map) | {
783+ if map. len ( ) > 0 {
784+ println ! (
785+ "{} dependencies: {}" ,
786+ console:: style( deps_type) . bold( ) . dim( ) ,
787+ console:: style( map. join( " \n -" ) ) . bold( ) . dim( )
788+ ) ;
789+ }
790+ } ) ;
791+ }
792+ let has_any_unallowed_dependent = detected_unallowed_dependencies. len ( ) > 0 ;
793+
794+ if has_any_unallowed_dependent {
795+ println ! ( "\n Update the {} value in the {} of the unallowed dependencies to solve the issue!" ,
796+ console:: style( "unallowed_dependents" ) . bold( ) . dim( ) ,
797+ console:: style( "bsconfig.json" ) . bold( ) . dim( )
798+ )
799+ }
800+ return !has_any_unallowed_dependent;
801+ }
802+
803+ #[ cfg( test) ]
804+ mod test {
805+ use crate :: bsconfig:: Source ;
806+ use ahash:: { AHashMap , AHashSet } ;
807+
808+ use super :: { Package , Namespace } ;
809+
810+ fn create_package (
811+ name : String ,
812+ bs_deps : Vec < String > ,
813+ pinned_deps : Vec < String > ,
814+ dev_deps : Vec < String > ,
815+ allowed_dependents : Option < Vec < String > > ,
816+ ) -> Package {
817+ return Package {
818+ name : name. clone ( ) ,
819+ bsconfig : crate :: bsconfig:: T {
820+ name : name. clone ( ) ,
821+ sources : crate :: bsconfig:: OneOrMore :: Single ( Source :: Shorthand ( String :: from ( "Source" ) ) ) ,
822+ package_specs : None ,
823+ warnings : None ,
824+ suffix : None ,
825+ pinned_dependencies : Some ( pinned_deps) ,
826+ bs_dependencies : Some ( bs_deps) ,
827+ bs_dev_dependencies : Some ( dev_deps) ,
828+ ppx_flags : None ,
829+ bsc_flags : None ,
830+ reason : None ,
831+ namespace : None ,
832+ jsx : None ,
833+ uncurried : None ,
834+ namespace_entry : None ,
835+ allowed_dependents,
836+ } ,
837+ source_folders : AHashSet :: new ( ) ,
838+ source_files : None ,
839+ namespace : Namespace :: Namespace ( String :: from ( "Package1" ) ) ,
840+ modules : None ,
841+ package_dir : String :: from ( "./something" ) ,
842+ dirs : None ,
843+ is_pinned_dep : false ,
844+ is_root : false ,
845+ } ;
846+ }
847+ #[ test]
848+ fn test_validate_packages_dependencies_unallowed_dependents_should_return_false_with_invalid_parents_as_bs_dependencies (
849+ ) {
850+ let mut packages: AHashMap < String , Package > = AHashMap :: new ( ) ;
851+ packages. insert (
852+ String :: from ( "Package1" ) ,
853+ create_package (
854+ String :: from ( "Package1" ) ,
855+ vec ! [ String :: from( "Package2" ) ] ,
856+ vec ! [ ] ,
857+ vec ! [ ] ,
858+ None ,
859+ ) ,
860+ ) ;
861+ packages. insert (
862+ String :: from ( "Package2" ) ,
863+ create_package (
864+ String :: from ( "Package2" ) ,
865+ vec ! [ ] ,
866+ vec ! [ ] ,
867+ vec ! [ ] ,
868+ Some ( vec ! [ String :: from( "Package3" ) ] ) ,
869+ ) ,
870+ ) ;
871+
872+ let is_valid = super :: validate_packages_dependencies ( & packages) ;
873+ assert_eq ! ( is_valid, false )
874+ }
875+
876+ #[ test]
877+ fn test_validate_packages_dependencies_unallowed_dependents_should_return_false_with_invalid_parents_as_pinned_dependencies (
878+ ) {
879+ let mut packages: AHashMap < String , Package > = AHashMap :: new ( ) ;
880+ packages. insert (
881+ String :: from ( "Package1" ) ,
882+ create_package (
883+ String :: from ( "Package1" ) ,
884+ vec ! [ ] ,
885+ vec ! [ String :: from( "Package2" ) ] ,
886+ vec ! [ ] ,
887+ None ,
888+ ) ,
889+ ) ;
890+ packages. insert (
891+ String :: from ( "Package2" ) ,
892+ create_package (
893+ String :: from ( "Package2" ) ,
894+ vec ! [ ] ,
895+ vec ! [ ] ,
896+ vec ! [ ] ,
897+ Some ( vec ! [ String :: from( "Package3" ) ] ) ,
898+ ) ,
899+ ) ;
900+
901+ let is_valid = super :: validate_packages_dependencies ( & packages) ;
902+ assert_eq ! ( is_valid, false )
903+ }
904+
905+ #[ test]
906+ fn test_validate_packages_dependencies_unallowed_dependents_should_return_false_with_invalid_parents_as_dev_dependencies (
907+ ) {
908+ let mut packages: AHashMap < String , Package > = AHashMap :: new ( ) ;
909+ packages. insert (
910+ String :: from ( "Package1" ) ,
911+ create_package (
912+ String :: from ( "Package1" ) ,
913+ vec ! [ ] ,
914+ vec ! [ ] ,
915+ vec ! [ String :: from( "Package2" ) ] ,
916+ None ,
917+ ) ,
918+ ) ;
919+ packages. insert (
920+ String :: from ( "Package2" ) ,
921+ create_package (
922+ String :: from ( "Package2" ) ,
923+ vec ! [ ] ,
924+ vec ! [ ] ,
925+ vec ! [ ] ,
926+ Some ( vec ! [ String :: from( "Package3" ) ] ) ,
927+ ) ,
928+ ) ;
929+
930+ let is_valid = super :: validate_packages_dependencies ( & packages) ;
931+ assert_eq ! ( is_valid, false )
932+ }
933+
934+ #[ test]
935+ fn test_validate_packages_dependencies_unallowed_dependents_should_return_true_with_no_invalid_parent ( ) {
936+ let mut packages: AHashMap < String , Package > = AHashMap :: new ( ) ;
937+ packages. insert (
938+ String :: from ( "Package1" ) ,
939+ create_package (
940+ String :: from ( "Package1" ) ,
941+ vec ! [ String :: from( "Package2" ) ] ,
942+ vec ! [ ] ,
943+ vec ! [ ] ,
944+ None ,
945+ ) ,
946+ ) ;
947+ packages. insert (
948+ String :: from ( "Package2" ) ,
949+ create_package (
950+ String :: from ( "Package2" ) ,
951+ vec ! [ ] ,
952+ vec ! [ ] ,
953+ vec ! [ ] ,
954+ Some ( vec ! [ String :: from( "Package1" ) ] ) ,
955+ ) ,
956+ ) ;
957+
958+ let is_valid = super :: validate_packages_dependencies ( & packages) ;
959+ assert_eq ! ( is_valid, true )
960+ }
961+ }
0 commit comments