@@ -444,7 +444,8 @@ def get_workspace_members(cls, workspaces, codebase, workspace_root_path):
444444 # Case 3: This is a complex glob pattern, we are doing a full codebase walk
445445 # and glob matching each resource
446446 else :
447- for resource in workspace_root_path :
447+ workspace_root = codebase .get_resource (path = workspace_root_path )
448+ for resource in workspace_root .walk (codebase ):
448449 if NpmPackageJsonHandler .is_datafile (resource .location ) and fnmatch .fnmatch (
449450 name = resource .location , pat = workspace_path ,
450451 ):
@@ -1155,6 +1156,10 @@ def parse(cls, location, package_only=False):
11551156 yield models .PackageData .from_data (package_data , package_only )
11561157
11571158
1159+ class UnknownPnpmLockFormat (Exception ):
1160+ pass
1161+
1162+
11581163class BasePnpmLockHandler (BaseNpmHandler ):
11591164
11601165 @classmethod
@@ -1181,31 +1186,62 @@ def parse(cls, location, package_only=False):
11811186 }
11821187 major_v , minor_v = lockfile_version .split ("." )
11831188
1184- 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+
11851211 dependencies_by_purl = {}
11861212
11871213 for purl_fields , data in resolved_packages .items ():
11881214 if major_v == "6" :
11891215 clean_purl_fields = purl_fields .split ("(" )[0 ]
11901216 elif major_v == "5" or is_shrinkwrap :
11911217 clean_purl_fields = purl_fields .split ("_" )[0 ]
1192- else :
1218+ elif major_v == "9" :
11931219 clean_purl_fields = purl_fields
1194- raise Exception (lockfile_version , purl_fields )
1220+ else :
1221+ message = f"Unknown pnpm lockfile format: { lockfile_version } "
1222+ raise UnknownPnpmLockFormat (message , purl_fields )
11951223
11961224 sections = clean_purl_fields .split ("/" )
1197- name_version = None
1225+ name_version = None
1226+ namespace = None
11981227 if major_v == "6" :
11991228 if len (sections ) == 2 :
1200- namespace = None
12011229 _ , name_version = sections
12021230 elif len (sections ) == 3 :
12031231 _ , 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
12041241
12051242 name , version = name_version .split ("@" )
12061243 elif major_v == "5" or is_shrinkwrap :
12071244 if len (sections ) == 3 :
1208- namespace = None
12091245 _ , name , version = sections
12101246 elif len (sections ) == 4 :
12111247 _ , namespace , name , version = sections
@@ -1223,7 +1259,21 @@ def parse(cls, location, package_only=False):
12231259
12241260 dependencies = data .get ('dependencies' ) or {}
12251261 optional_dependencies = data .get ('optionalDependencies' ) or {}
1226- 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+
12271277 peer_dependencies = data .get ('peerDependencies' ) or {}
12281278 peer_dependencies_meta = data .get ('peerDependenciesMeta' ) or {}
12291279
0 commit comments