@@ -1156,6 +1156,10 @@ def parse(cls, location, package_only=False):
11561156 yield models .PackageData .from_data (package_data , package_only )
11571157
11581158
1159+ class UnknownPnpmLockFormat (Exception ):
1160+ pass
1161+
1162+
11591163class BasePnpmLockHandler (BaseNpmHandler ):
11601164
11611165 @classmethod
@@ -1182,31 +1186,62 @@ def parse(cls, location, package_only=False):
11821186 }
11831187 major_v , minor_v = lockfile_version .split ("." )
11841188
1185- resolved_packages = lock_data .get ("packages" , [])
1189+ resolved_packages = lock_data .get ("packages" , {})
1190+ dependency_relations = lock_data .get ("snapshots" , {})
1191+ dependency_relations_by_purl = {}
1192+ if dependency_relations :
1193+ for purl_fields , relations in dependency_relations .items ():
1194+ clean_purl_fields = purl_fields .split ("(" )[0 ]
1195+ sections = clean_purl_fields .split ("/" )
1196+ namespace = None
1197+ if len (sections ) == 2 :
1198+ namespace , name_version = sections
1199+ elif len (sections ) == 1 :
1200+ name_version , = sections
1201+ name , version = name_version .split ("@" )
1202+
1203+ purl = PackageURL (
1204+ type = cls .default_package_type ,
1205+ name = name ,
1206+ namespace = namespace ,
1207+ version = version ,
1208+ ).to_string ()
1209+ dependency_relations_by_purl [purl ] = relations
1210+
11861211 dependencies_by_purl = {}
11871212
11881213 for purl_fields , data in resolved_packages .items ():
11891214 if major_v == "6" :
11901215 clean_purl_fields = purl_fields .split ("(" )[0 ]
11911216 elif major_v == "5" or is_shrinkwrap :
11921217 clean_purl_fields = purl_fields .split ("_" )[0 ]
1193- else :
1218+ elif major_v == "9" :
11941219 clean_purl_fields = purl_fields
1195- raise Exception (lockfile_version , purl_fields )
1220+ else :
1221+ message = f"Unknown pnpm lockfile format: { lockfile_version } "
1222+ raise UnknownPnpmLockFormat (message , purl_fields )
11961223
11971224 sections = clean_purl_fields .split ("/" )
1198- name_version = None
1225+ name_version = None
1226+ namespace = None
11991227 if major_v == "6" :
12001228 if len (sections ) == 2 :
1201- namespace = None
12021229 _ , name_version = sections
12031230 elif len (sections ) == 3 :
12041231 _ , namespace , name_version = sections
1232+ elif len (sections ) == 1 :
1233+ name_version , = sections
1234+
1235+ name , version = name_version .split ("@" )
1236+ elif major_v == "9" :
1237+ if len (sections ) == 2 :
1238+ namespace , name_version = sections
1239+ elif len (sections ) == 1 :
1240+ name_version , = sections
12051241
12061242 name , version = name_version .split ("@" )
12071243 elif major_v == "5" or is_shrinkwrap :
12081244 if len (sections ) == 3 :
1209- namespace = None
12101245 _ , name , version = sections
12111246 elif len (sections ) == 4 :
12121247 _ , namespace , name , version = sections
@@ -1224,7 +1259,21 @@ def parse(cls, location, package_only=False):
12241259
12251260 dependencies = data .get ('dependencies' ) or {}
12261261 optional_dependencies = data .get ('optionalDependencies' ) or {}
1227- transitive_peer_dependencies = data .get ('transitivePeerDependencies' ) or {}
1262+ transitive_peer_dependencies = data .get ('transitivePeerDependencies' ) or []
1263+
1264+ if purl in dependency_relations_by_purl :
1265+ dependency_relations = dependency_relations_by_purl .get (purl )
1266+ if dependency_relations :
1267+ deps = dependency_relations .get ('dependencies' )
1268+ if deps :
1269+ dependencies .update (deps )
1270+ optional_deps = dependency_relations .get ('optionalDependencies' )
1271+ if optional_deps :
1272+ optional_dependencies .update (optional_deps )
1273+ transitive_peer_deps = dependency_relations .get ('transitivePeerDependencies' )
1274+ if transitive_peer_deps :
1275+ transitive_peer_dependencies .extend (transitive_peer_deps )
1276+
12281277 peer_dependencies = data .get ('peerDependencies' ) or {}
12291278 peer_dependencies_meta = data .get ('peerDependenciesMeta' ) or {}
12301279
0 commit comments