@@ -51,7 +51,8 @@ WARNING: `update_pnpm_lock` attribute in `npm_translate_lock(name = "{rctx_name}
5151 _init_patched_dependencies_labels (priv , rctx , attr , label_store )
5252
5353 # May depend on lockfile state
54- _init_root_package (priv , rctx , attr , label_store )
54+ _init_root_package (priv , attr , label_store )
55+ _init_workspace (priv , rctx , label_store , is_windows )
5556
5657 if _should_update_pnpm_lock (priv ):
5758 _init_importer_labels (priv , label_store )
@@ -167,7 +168,7 @@ def _init_external_repository_action_cache(priv, attr):
167168 priv ["external_repository_action_cache" ] = attr .external_repository_action_cache if attr .external_repository_action_cache else utils .default_external_repository_action_cache ()
168169
169170################################################################################
170- def _init_root_package (priv , rctx , attr , label_store ):
171+ def _init_root_package (priv , attr , label_store ):
171172 pnpm_lock_label = label_store .label ("pnpm_lock" )
172173
173174 # use the directory of the pnpm_lock file as the root_package unless overridden by the root_package attribute
@@ -184,19 +185,46 @@ def _init_root_package(priv, rctx, attr, label_store):
184185 fail ("root_package cannot be overridden if there are pnpm workspace packages specified" )
185186 priv ["root_package" ] = attr .root_package
186187
187- # Load a declared root package.json
188+ def _init_workspace (priv , rctx , label_store , is_windows ):
189+ root_package_json = {}
190+
191+ # Load pnpm settings from root package.json for pnpm <= v9.
188192 if label_store .has ("package_json_root" ):
193+ # Load a declared root package.json
189194 root_package_json_path = label_store .path ("package_json_root" )
190- priv [ " root_package_json" ] = json .decode (rctx .read (root_package_json_path ))
195+ root_package_json = json .decode (rctx .read (root_package_json_path ))
191196 elif "." in priv ["importers" ].keys ():
192197 # Load an undeclared package.json derived from the root importer in the lockfile
193198 label_store .add_sibling ("lock" , "package_json_root" , PACKAGE_JSON_FILENAME )
194199 root_package_json_path = label_store .path ("package_json_root" )
195- priv ["root_package_json" ] = json .decode (rctx .read (root_package_json_path ))
196- else :
197- # if there is no root importer that means there is no root package.json to read; pnpm allows
198- # you to just have a pnpm-workspaces.yaml at the root and no package.json at that location
199- priv ["root_package_json" ] = {}
200+ root_package_json = json .decode (rctx .read (root_package_json_path ))
201+
202+ priv ["pnpm_settings" ] = root_package_json .get ("pnpm" , {})
203+
204+ # Read settings from pnpm-workspace.yaml for pnpm v10+ (NOTE: pnpm 9-10+ has lockfile version 9).
205+ # Support scenario where pnpm-lock.yaml was never parsed and "lock_version" is not set.
206+ if label_store .has ("pnpm_workspace" ):
207+ pnpm_workspace_path = label_store .path ("pnpm_workspace" )
208+ if is_windows or utils .exists (rctx , pnpm_workspace_path ):
209+ pnpm_workspace_json , workspace_parse_err = _yaml_to_json (rctx , str (pnpm_workspace_path ), is_windows )
210+
211+ if workspace_parse_err == None :
212+ pnpm_workspace_settings , workspace_parse_err = pnpm .parse_pnpm_workspace_json (pnpm_workspace_json )
213+
214+ if pnpm_workspace_settings :
215+ priv ["pnpm_settings" ] = priv ["pnpm_settings" ] | pnpm_workspace_settings
216+
217+ if workspace_parse_err != None :
218+ should_update = _should_update_pnpm_lock (priv )
219+ msg = """
220+ {type}: pnpm-workspace.yaml parse error {error}`.
221+ """ .format (type = "WARNING" if should_update else "ERROR" , error = workspace_parse_err )
222+
223+ if should_update :
224+ # buildifier: disable=print
225+ print (msg )
226+ else :
227+ fail (msg )
200228
201229################################################################################
202230def _init_npmrc (priv , rctx , attr , label_store ):
@@ -444,24 +472,33 @@ WARNING: Cannot determine home directory in order to load home `.npmrc` file in
444472 _load_npmrc (priv , rctx , home_npmrc_path )
445473
446474################################################################################
447- def _load_lockfile (priv , rctx , attr , pnpm_lock_path , is_windows ):
448- importers = {}
449- packages = {}
450- patched_dependencies = {}
451- lock_parse_err = None
452-
475+ def _yaml_to_json (rctx , yaml_path , is_windows ):
453476 host_yq = Label ("@yq_{}//:yq{}" .format (repo_utils .platform (rctx ), ".exe" if is_windows else "" ))
454477 yq_args = [
455478 str (rctx .path (host_yq )),
456- str (pnpm_lock_path ),
479+ str (yaml_path ),
457480 "-o=json" ,
458481 ]
459482 result = rctx .execute (yq_args )
460483 if result .return_code :
461- lock_parse_err = "failed to parse pnpm lock file with yq. '{}' exited with {}: \n STDOUT:\n {}\n STDERR:\n {}" .format (" " .join (yq_args ), result .return_code , result .stdout , result .stderr )
462- else :
484+ return None , "failed to parse {} with yq. '{}' exited with {}: \n STDOUT:\n {}\n STDERR:\n {}" .format (" " .join (yq_args ), yaml_path , result .return_code , result .stdout , result .stderr )
485+
486+ # NB: yq will return the string "null" if the yaml file is empty
487+ if result .stdout != "null" :
488+ return result .stdout , None
489+
490+ return None , None
491+
492+ def _load_lockfile (priv , rctx , attr , pnpm_lock_path , is_windows ):
493+ importers = {}
494+ packages = {}
495+ patched_dependencies = {}
496+ lock_parse_err = None
497+
498+ lockfile_content , lock_parse_err = _yaml_to_json (rctx , str (pnpm_lock_path ), is_windows )
499+ if lock_parse_err == None :
463500 importers , packages , patched_dependencies , lock_parse_err = pnpm .parse_pnpm_lock_json (
464- result . stdout if result . stdout != "null" else None , # NB: yq will return the string "null" if the yaml file is empty
501+ lockfile_content ,
465502 attr .no_dev ,
466503 attr .no_optional ,
467504 )
@@ -507,7 +544,7 @@ def _patched_dependencies(priv):
507544 return priv ["patched_dependencies" ]
508545
509546def _only_built_dependencies (priv ):
510- return _root_package_json (priv ). get ( "pnpm" , {} ).get ("onlyBuiltDependencies" , None )
547+ return _pnpm_settings (priv ).get ("onlyBuiltDependencies" , None )
511548
512549def _num_patches (priv ):
513550 return priv ["num_patches" ]
@@ -521,8 +558,8 @@ def _npm_auth(priv):
521558def _root_package (priv ):
522559 return priv ["root_package" ]
523560
524- def _root_package_json (priv ):
525- return priv ["root_package_json " ]
561+ def _pnpm_settings (priv ):
562+ return priv ["pnpm_settings " ]
526563
527564################################################################################
528565def _new (rctx_name , rctx , attr ):
@@ -543,7 +580,7 @@ def _new(rctx_name, rctx, attr):
543580 "npm_registries" : {},
544581 "packages" : {},
545582 "root_package" : attr .root_package ,
546- "root_package_json " : {},
583+ "pnpm_settings " : {},
547584 "patched_dependencies" : {},
548585 "should_update_pnpm_lock" : should_update_pnpm_lock ,
549586 }
0 commit comments