Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for finding pnpm workspace packages #39

Merged
merged 1 commit into from
Feb 2, 2020

Conversation

Andarist
Copy link
Collaborator

No description provided.

if (dir === undefined) {
return firstPkgJsonDirectory;

let singlePackageRoot = await findWorkspacesUp({ cwd, tools: ["root"] });
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite unsure why this is needed (but there is an explicit test for it). manypkg is by definition supposed to help with validating monorepo setups, so i dont understand why a single package mode is supported?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It exists so that other tools can use this even though it's not Manypkg's use case. (I have some ideas in mind where this will be necessary)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some ideas in mind where this will be necessary

Could you share them? I'm trying to understand the whole context, so that would be helpful to me

Copy link
Member

@emmatown emmatown Jan 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main one I have right now is a minimal wrapper around npm, pnpm, Yarn and possibly Bolt that chooses the right tool given a repo and lets you do installs and run scripts/binaries and I want it to work on single package repos as well.

@Andarist Andarist requested a review from emmatown January 26, 2020 22:15
@@ -1,6 +1,5 @@
import findUp from "find-up";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you replace this file with what's below? (I started writing this a little bit ago but hadn't written tests yet and I think it'll be a little faster than yours since it won't do the globbing and the pnpm file checking will happen in parallel with the package.json reading)

import findUp from "find-up";
import path from "path";
import fs from "fs-extra";

export class NoPkgJsonFound extends Error {
  directory: string;
  constructor(directory: string) {
    super(
      `No package.json could be found upwards from the directory ${directory}`
    );
    this.directory = directory;
  }
}

async function hasWorkspacesConfiguredViaPkgJson(
  directory: string,
  firstPkgJsonDirRef: { current: string | undefined }
) {
  try {
    let pkgJson = await fs.readJson(path.join(directory, "package.json"));
    if (firstPkgJsonDirRef.current === undefined) {
      firstPkgJsonDirRef.current = directory;
    }
    if (pkgJson.workspaces || pkgJson.bolt) {
      return directory;
    }
  } catch (err) {
    if (err.code !== "ENOENT") {
      throw err;
    }
  }
}

async function hasWorkspacesConfiguredViaPnpm(directory: string) {
  // @ts-ignore
  let pnpmWorkspacesFileExists = await fs.exists(
    path.join(directory, "pnpm-workspace.yaml")
  );
  if (pnpmWorkspacesFileExists) {
    return directory;
  }
}

export default async function findWorkspacesRoot(cwd: string): Promise<string> {
  let firstPkgJsonDirRef: { current: string | undefined } = {
    current: undefined
  };
  let dir = await findUp(
    directory => {
      return Promise.all([
        hasWorkspacesConfiguredViaPkgJson(directory, firstPkgJsonDirRef),
        hasWorkspacesConfiguredViaPnpm(directory)
      ]).then(x => x.find(dir => dir));
    },
    { cwd, type: "directory" }
  );
  if (firstPkgJsonDirRef.current === undefined) {
    throw new NoPkgJsonFound(cwd);
  }
  if (dir === undefined) {
    return firstPkgJsonDirRef.current;
  }
  return dir;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, my main motivation for this was to just reuse get-workspaces logic, because on the high level we want both of those (get-workspaces and find-workspaces-root) to match. There are other types of workspaces config (for example lerna) and when you add support for those you need to always keep those two in sync (if you implement each of them separately).

This check is not really happening that often, so I wasn't really concerned with perf as it should be rather sufficient anyway - especially given that manypkg is primarily for monorepo usage, so doing a second fs traversal for single package roots should happen really rarely.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other types of workspaces config (for example lerna) and when you add support for those you need to always keep those two in sync (if you implement each of them separately).

Yeah, that's certainly a potential concern. I think it's acceptable for this because there won't be that many types of workspaces config.

This check is not really happening that often, so I wasn't really concerned with perf as it should be rather sufficient anyway - especially given that manypkg is primarily for monorepo usage, so doing a second fs traversal for single package roots should happen really rarely.

That's certainly true for Manypkg but for the usecase I mentioned in #39 (comment) it will be a lot more important (e.g. importing globby and its deps takes ~500ms iirc which is likely too slow for that use case)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A potential idea that could alleviate this concern - splitting the logic of get-workspaces into two parts: determining the workspace type (yarn, bolt, pnpm, others) & resolving the workspace packages. That way we could just reuse the first one here and as to the concern of importing globby being slow:

  • either split get-workspaces into two packages
  • or use "lazy" mode of Babel's commonjs transform

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess splitting the logic of get-workspaces would be fine but I feel like it's not enough code for it to matter much so IMO the best thing to do would be to move get-workspaces into this repo (@Noviny do you have any problems with this?) so that we can easily keep them in sync.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on this, I'm happy to use the implementation here because I've decided to write the previously mentioned tool in Rust.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, which one do you want to write in Rust?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapper around the various package managers to install packages and run scripts and binaries

Copy link
Member

@emmatown emmatown left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!!

@emmatown emmatown merged commit 0ed3f2b into Thinkmill:master Feb 2, 2020
@github-actions github-actions bot mentioned this pull request Feb 2, 2020
@Andarist Andarist deleted the pnpm-support branch February 2, 2020 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants