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

[base-controller] Fix any usage in BaseControllerV1 #3959

Merged
merged 8 commits into from
Feb 27, 2024

Conversation

MajorLift
Copy link
Contributor

@MajorLift MajorLift commented Feb 22, 2024

Explanation

  • For runtime property assignment, use as unknown as instead of as any.
  • Change the types for BaseControllerV1 class fields initialConfig, initialState from C, S to Partial<C>, Partial<S>.
    • Initial user-supplied constructor options do not need to be complete C, S objects, since internal{Config,State} will be populated with default{Config,State}.
  • For empty objects, prefer no type assertions or as never (never is assignable to all types).
  • Fix code written based on outdated TypeScript limitation.

References

Changelog

@metamask/base-controller

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

@MajorLift MajorLift self-assigned this Feb 22, 2024
@MajorLift MajorLift force-pushed the 240222-base-controller-fix-any branch from 19671cf to c6e4651 Compare February 22, 2024 18:32
@MajorLift MajorLift marked this pull request as ready for review February 22, 2024 18:37
@MajorLift MajorLift requested a review from a team as a code owner February 22, 2024 18:37
@MajorLift MajorLift force-pushed the 240222-base-controller-fix-any branch from c6e4651 to 0bd4386 Compare February 22, 2024 18:47
@MajorLift MajorLift changed the title Fix any usage in BaseControllerV1 [base-controller] Fix any usage in BaseControllerV1 Feb 22, 2024
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- **BREAKING:** Change the types for `BaseControllerV1` class fields `initialConfig`, `initialState` from `C`, `S` to `Partial<C>`, `Partial<S>` ([#3959](https://github.com/MetaMask/core/pull/3959))
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like these are private properties, so is this breaking?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The constructor options config, state are handled slightly differently since there's no type assertion for the default parameter, but this probably doesn't warrant a changelog entry much less as a breaking change. Removed: 0a66987

### Changed

- **BREAKING:** Change the types for `BaseControllerV1` class fields `initialConfig`, `initialState` from `C`, `S` to `Partial<C>`, `Partial<S>` ([#3959](https://github.com/MetaMask/core/pull/3959))
- **BREAKING:** Convert `BaseConfig`, `BaseState` interfaces to types ([#3959](https://github.com/MetaMask/core/pull/3959))
Copy link
Contributor

@mcmire mcmire Feb 23, 2024

Choose a reason for hiding this comment

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

Since we're aiming to remove BaseControllerV1, maybe we don't worry about converting these types? This way we can avoid a breaking change, at least for this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted here: 8347a2a

@MajorLift MajorLift force-pushed the 240222-base-controller-fix-any branch from 6ab2e37 to 8347a2a Compare February 26, 2024 14:03
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

Looks good!

@MajorLift MajorLift merged commit eda5b9d into main Feb 27, 2024
138 checks passed
@MajorLift MajorLift deleted the 240222-base-controller-fix-any branch February 27, 2024 00:08
MajorLift added a commit that referenced this pull request Aug 20, 2024
… safeguards (#4467)

## Overview

This commit fixes issues with the `ComposableController` class's
interface, and its logic for validating V1 and V2 controllers.

These changes will enable `ComposableController` to function correctly
downstream in the Mobile Engine, and eventually the Wallet Framework
POC.

## Explanation

The previous approach of generating mock controller classes from the
`ComposableControllerState` input using the `GetChildControllers` was
flawed, because the mock controllers would always be incomplete,
complicating attempts at validation.

Instead, we now rely on the downstream consumer to provide both a
composed type of state schemas (`ComposableControllerState`) and a type
union of the child controller instances (`ChildControllers`). For
example, in mobile, we can use (with some adjustments) `EngineState` for
the former, and `Controllers[keyof Controllers]` for the latter.

The validation logic for V1 controllers has also been updated. Due to
breaking changes made to the private properties of `BaseControllerV1`
(#3959), mobile V1 controllers
relying on versions prior to these changes were introduced were
incompatible with the up-to-date `BaseControllerV1` version that the
composable-controller package references.

In this commit, the validator type `BaseControllerV1Instance` filters
out the problematic private properties by using the `PublicInterface`
type. Because the public API of `BaseControllerV1` has been relatively
constant, this removes the type errors that previously occurred in
mobile when passing V1 controllers into `ComposableController`.

## References

- Closes #4448
- Contributes to #4213
- Next steps MetaMask/metamask-mobile#10073
  - See MetaMask/metamask-mobile#10011

## Changelog

### `@metamask/composable-controller` (major)

### Changed

- **BREAKING:** Add two required generic parameters to the
`ComposableController` class: `ComposedControllerState` (constrained by
`LegacyComposableControllerStateConstraint`) and `ChildControllers`
(constrained by `ControllerInstance`)
([#4467](#4467)).
- **BREAKING:** The type guard `isBaseController` now validates that the
input has an object-type property named `metadata` in addition to its
existing checks.
- **BREAKING:** The type guard `isBaseControllerV1` now validates that
the input has object-type properties `config`, `state`, and
function-type property `subscribe`, in addition to its existing checks.
- **BREAKING:** Narrow `LegacyControllerStateConstraint` type from
`BaseState | StateConstraint` to `BaseState & object | StateConstraint`.
- Add an optional generic parameter `ControllerName` to the
`RestrictedControllerMessengerConstraint` type, which extends `string`
and defaults to `string`.
 
### Fixed

- **BREAKING:** The `ComposableController` class raises a type error if
a non-controller with no `state` property is passed into the
`ChildControllers` generic parameter or the `controllers` constructor
option.
- Previously, a runtime error was thrown at class instantiation with no
type-level enforcement.
- When the `ComposableController` class is instantiated, its messenger
now attempts to subscribe to all child controller `stateChange` events
that are included in the messenger's events allowlist.
- This was always the expected behavior, but a bug introduced in
`@metamask/[email protected]` caused `stateChange` event
subscriptions to fail.
- `isBaseController` and `isBaseControllerV1` no longer return false
negatives.
- The `instanceof` operator is no longer used to validate that the input
is a subclass of `BaseController` or `BaseControllerV1`.
- The `ChildControllerStateChangeEvents` type checks that the child
controller's state extends from the `StateConstraintV1` type instead of
from `Record<string, unknown>`.
([#4467](#4467))
- V1 controllers define their state types using the `interface` keyword,
which are incompatible with `Record<string, unknown>` by default. This
resulted in `ChildControllerStateChangeEvents` failing to generate
`stateChange` events for V1 controllers and returning `never`.

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

base-controller: Replace use of any with proper types (non-test files only)
2 participants