Skip to content

Generate paths for modular add#2111

Merged
cristiano-belloni merged 17 commits intomainfrom
fix/nested-package-names
Sep 14, 2022
Merged

Generate paths for modular add#2111
cristiano-belloni merged 17 commits intomainfrom
fix/nested-package-names

Conversation

@cristiano-belloni
Copy link
Contributor

@cristiano-belloni cristiano-belloni commented Sep 6, 2022

TODO

Revised proposition with use-cases:

  1. When a user wants to add an unscoped package to the packages root
# adds "pkg" in ./packages/pkg
modular add PKG
  1. When a user wants to add an unscoped package to a nested path
# adds "pkg" in packages/my/nested/path/pkg
modular add pkg --path packages/my/nested/path
  1. When a user wants to add a scoped package
# adds "@scope/pkg" in packages/pkg
modular add @scope/pkg
  1. When a user wants to add a scoped package to a nested path
# adds "@scope/pkg" in packages/my/nested/path/scope/pkg
modular add @scope/pkg --path packages/my/nested/path/scope
  1. When a user wants to add a package (scoped or otherwise) to a path other than ./packages
# adds "pkg" in my/other/path/pkg
modular add pkg --path /my/other/path

# adds "@scope/pkg" in my/other/path/pkg
modular add @scope/PKG --path my/other/path

Validity checks (from @steveukx 's comment):

  • Assuming --path contains a relative directory (would need to validate doesn't use .. blocks to jump outside of repo root) that can be used in place of the default ./packages.

  • Caveat of using a --path, modular should check that the workspace would find the newly created package with the workspaces property in root package.json

Additional checks

  • Modular now checks for the existence of a package with the same name, using the workspace resolver. Before, if a workspace with the same name already existed, Modular would still add a new one, but Yarn would error at the end of the command, giving the impression that the command failed. Now the command fails straight away.

  • Modular now checks for the existence of the target directory and fail if the directory is not empty. Before, it just silently wrote in the existing directory without clearing it first (potentially overwriting some, but not necessarily all, files).

@changeset-bot
Copy link

changeset-bot bot commented Sep 6, 2022

🦋 Changeset detected

Latest commit: 8cdfc02

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
modular-scripts Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coveralls
Copy link
Collaborator

coveralls commented Sep 6, 2022

Coverage Status

Coverage decreased (-0.5%) to 33.419% when pulling 8cdfc02 on fix/nested-package-names into e41effa on main.

export const packageRegex =
/^(@[a-z0-9-~][a-z0-9-._~]*)?\/?([a-z0-9-~][a-z0-9-._~]*)\/?(.*)/;

export function parsePackageName(name: string): {
Copy link
Contributor

Choose a reason for hiding this comment

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

This could do with a docstring with some examples of what each of the return values are.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

const installedPackageJsonPath = path.join(templateName, 'package.json');

const { dependencyName: packageName, scope, module } = parsePackageName(name);
const { componentName, packagePath } = getNewPackageDetails({
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest that it would be cleaner to call getNewPackageDetails(name) and return { packageName, packagePath, componentName }. This would move the call to parsePackageName into getNewPackageDetails and avoid declaring the scope and module variables in the scope of promptForName when they are only used once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

}: AddOptions): Promise<void> {
const name = await promptForName(nameArg || unstableName);

// Validate package name
Copy link
Contributor

Choose a reason for hiding this comment

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

This entire validation section from 146 to 174 looks like it could go into a separate function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

let newModularPackageJsonPath;

// try and find the modular template packge, if it's already been installed
// Find out if a package with the same name already exists
Copy link
Contributor

Choose a reason for hiding this comment

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

This entire validation section from 190 to 208 looks like it could also go into a separate function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


// try and find the modular template packge, if it's already been installed
// Find out if a package with the same name already exists
if ((await getWorkspaceInfo())[packageName]) {
Copy link
Contributor

Choose a reason for hiding this comment

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

How long does this take in a large monorepo (e.g. 100-500 packages)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sgb-io ran benchmarks on that, and we're < 2ms for 1k workspaces.

}

// This function gets all the globs in "workspaces" field in the root package manifest
export async function getWorkspaceGlobs(): Promise<string[]> {
Copy link
Contributor

Choose a reason for hiding this comment

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

As this module exports 2 different workspace-related functions, perhaps it would better be called workspaces (i.e. this is where all utils for workspaces are placed).

Copy link
Contributor

Choose a reason for hiding this comment

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

The second export isn't currently used in the project, so this could be private to the module

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the export

@cristiano-belloni cristiano-belloni marked this pull request as ready for review September 9, 2022 14:51
sgb-io
sgb-io previously approved these changes Sep 12, 2022
Copy link
Contributor

@sgb-io sgb-io left a comment

Choose a reason for hiding this comment

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

LGTM

# `modular add <packageName>`

Adds a new package by creating a new workspace at `packages/<packagePath>`
Adds a new package by creating a new workspace at `packages/<packageName>`,
Copy link
Contributor

Choose a reason for hiding this comment

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

How about we have the 5 examples from the discussion thread right in the docs? I think it makes it really fast to understand how to use the option (even though your written docs are also good!)

// Try and find the modular template package. If it's already been installed
// in the project then continue without needing to do an install.
// else we will fetch it from the yarn registry.
let newModularPackageJsonPath;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: not related to your change, but this could he instantiated with an explicit string | undefined type

@cristiano-belloni cristiano-belloni merged commit deaee2c into main Sep 14, 2022
@cristiano-belloni cristiano-belloni deleted the fix/nested-package-names branch September 14, 2022 10:19
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.

5 participants