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

Categorize type-only and controller-messaged deps correctly #4449

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mcmire
Copy link
Contributor

@mcmire mcmire commented Jun 21, 2024

Explanation

There are two special kinds of dependencies that have been frequently miscategorized:

  • Type-only dependencies: These are dependencies from which no runtime code is used, but only TypeScript types. Since consumers need these types in order to write TypeScript code, these should be listed under dependencies (not devDependencies).
  • Controller-messaged dependencies. Say that controller A talks to controller B. Controller B in this case needs to be a dependency of A. Furthermore, a project that wants to use controller A needs to instantiate B before A. Because of the intercommunication between these controllers, in order to prevent runtime errors, the version of controller B that A relies on must match the version of B that the project relies on. To enforce this, B must be listed under A's peerDependencies, even if it is also listed under its dependencies.

This commit corrects dependencies for each package in the monorepo such that they follow the rules above. In rare cases dependencies that were completely used in production code were listed under devDependencies. These have been corrected as well.

References

Fixes #2062, and related (but unfiled) problems.

Changelog

(Updated in PR)

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@mcmire mcmire force-pushed the correct-type-only-and-messenger-deps branch from ca3d2f3 to 0166adf Compare June 21, 2024 22:28
There are two special kinds of dependencies that have been frequently
miscategorized:

- Type-only dependencies: These are dependencies from which no runtime
  code is used, but only TypeScript types. Since consumers need these
  types in order to write TypeScript code, these should be listed under
  `dependencies` (not `devDependencies`).
- Controller-messaged dependencies. Say that controller A talks to
  controller B. Controller B in this case needs to be a dependency of A.
  Furthermore, a project that wants to use controller A needs to
  instantiate B before A. Because of the intercommunication between
  these controllers, in order to prevent runtime errors, the version of
  controller B that A relies on must match the version of B that the
  _project_ relies on. To enforce this, B must be listed under A's
  `peerDependencies`, even if it is also listed under its
  `dependencies`.

This commit corrects dependencies for each package in the monorepo such
that they follow the rules above. In rare cases dependencies that were
completely used in production code were listed under `devDependencies`.
These have been corrected as well.
@mcmire mcmire force-pushed the correct-type-only-and-messenger-deps branch from 0166adf to b7434cb Compare June 21, 2024 22:29
@mcmire mcmire marked this pull request as ready for review June 21, 2024 22:31
@mcmire mcmire requested review from a team as code owners June 21, 2024 22:31
@mcmire mcmire requested a review from a team June 21, 2024 22:32
@Gudahtt
Copy link
Member

Gudahtt commented Jun 24, 2024

Since consumers need these types in order to write TypeScript code, these should be listed under dependencies (not devDependencies).

This seems like a misunderstanding. It's not typically the case that consumers would need the same type dependencies to be in the dependency tree in order to use a package's types.

This is only the case when another packages types are exported directly. If that happens, that dependency's types will also end up directly referenced in the resulting types. Any project using this package would need to have the package the types come from as well, or it would be an invalid reference.

But that's not true when the types aren't exported. If they're just used internally by the package, they don't exist at all for package consumers. This is more commonly the case, and in general I think we should avoid exporting third-party types so that our packages can have fewer dependencies.

You can see some examples of what I mean in this diff. If you build all packages and look at packages/accounts-controller/dist/types/AccountsController.d.ts, you can see this:

import type { SnapStateChange } from '@metamask/snaps-controllers';
...
export type AllowedEvents = SnapStateChange | KeyringControllerStateChangeEvent;

That type comes from @metamask/snaps-controllers and is exported directly. We'd need to ensure that @metamask/snaps-controllers is present for users of this package in order for these types to remain valid.

However, if you look at the two packages you've moved to dependencies in assets-controllers (@metamask/keyring-api and @types/lodash), neither of them appear in the built types. They are only needed at build-time, they aren't used at all by consumers of this package.

@Gudahtt
Copy link
Member

Gudahtt commented Jun 24, 2024

Additionally, in general we should never have a package listed as both a peerDependency and a dependency. If something is a peerDependency, it means that we expect the user of the package to bring their own copy. It would be a contradiction to list it as a dependency in that case; we'd be asking them to bring their own copy, but we'd have ours as well. The whole point of a peerDependency is that we don't know which version is correct to use. We need to rely upon the user of the package to be responsible for having the correct version.

Every peerDependency should be listed as a devDependency so that the package is present here for our tests to run, but it should never be a dependency.

@mcmire
Copy link
Contributor Author

mcmire commented Jun 24, 2024

Thanks for the feedback! I have to think about this a bit more. Moving to draft in the meantime.

@mcmire mcmire marked this pull request as draft June 24, 2024 22:27
@mcmire
Copy link
Contributor Author

mcmire commented Jun 26, 2024

I've thought about it and your suggestion makes sense. It sounds like I need to adjust the constraints to disallow a package from appearing in both dependencies and peerDependencies, and perhaps to add some documentation around how to represent controller dependencies effectively.

I'll return to this after we've upgraded to Yarn v4 and converted the constraints to JavaScript, because I think it'll be easier to modify the constraints then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants