Skip to content

Commit

Permalink
fix: support both formats of workspace definition for npm and yarn (v…
Browse files Browse the repository at this point in the history
…ercel#3235)

We can support both by creating an [untagged
enum](https://serde.rs/enum-representations.html#untagged) in serde.
Quick spot checked the issue we saw on `vercel/vercel` and it no longer
happens with this shim.
  • Loading branch information
chris-olszewski authored Jan 10, 2023
1 parent 2713884 commit 5aae345
Showing 1 changed file with 39 additions and 3 deletions.
42 changes: 39 additions & 3 deletions crates/turborepo-lib/src/package_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,32 @@ struct PnpmWorkspaces {

#[derive(Debug, Deserialize)]
struct PackageJsonWorkspaces {
pub workspaces: Vec<String>,
workspaces: Workspaces,
}

#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
#[serde(untagged)]
enum Workspaces {
TopLevel(Vec<String>),
Nested { packages: Vec<String> },
}

impl AsRef<[String]> for Workspaces {
fn as_ref(&self) -> &[String] {
match self {
Workspaces::TopLevel(packages) => packages.as_slice(),
Workspaces::Nested { packages } => packages.as_slice(),
}
}
}

impl From<Workspaces> for Vec<String> {
fn from(value: Workspaces) -> Self {
match value {
Workspaces::TopLevel(packages) => packages,
Workspaces::Nested { packages } => packages,
}
}
}

pub enum PackageManager {
Expand Down Expand Up @@ -70,13 +95,13 @@ impl PackageManager {
let package_json_text = fs::read_to_string(root_path.join("package.json"))?;
let package_json: PackageJsonWorkspaces = serde_json::from_str(&package_json_text)?;

if package_json.workspaces.is_empty() {
if package_json.workspaces.as_ref().is_empty() {
return Err(anyhow!(
"package.json: no packages found. Turborepo requires packages to be \
defined in the root package.json"
));
} else {
package_json.workspaces
package_json.workspaces.into()
}
}
};
Expand Down Expand Up @@ -117,4 +142,15 @@ mod tests {
vec![PathBuf::from("apps/*"), PathBuf::from("packages/*")]
);
}

#[test]
fn test_nested_workspace_globs() -> Result<()> {
let top_level: PackageJsonWorkspaces =
serde_json::from_str("{ \"workspaces\": [\"packages/**\"]}")?;
assert_eq!(top_level.workspaces.as_ref(), vec!["packages/**"]);
let nested: PackageJsonWorkspaces =
serde_json::from_str("{ \"workspaces\": {\"packages\": [\"packages/**\"]}}")?;
assert_eq!(nested.workspaces.as_ref(), vec!["packages/**"]);
Ok(())
}
}

0 comments on commit 5aae345

Please sign in to comment.