All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Rename
ControllerMessenger
toMessenger
(#5050)ControllerMessenger
has been renamed toMessenger
RestrictedControllerMessengerConstraint
has been renamed toRestrictedMessengerConstraint
RestrictedControllerMessenger
has been renamed toRestrictedMessenger
- The
RestrictedMessenger
constructor parametercontrollerMessenger
has been renamed tomessenger
, though the old name is still accepted - The old names remain exported as deprecated aliases of the new names, so this is not a breaking change.
- Bump
@metamask/utils
from^9.1.0
to^10.0.0
(#4831)
- Produce and export ESM-compatible TypeScript type declaration files in addition to CommonJS-compatible declaration files (#4648)
- Previously, this package shipped with only one variant of type declaration
files, and these files were only CommonJS-compatible, and the
exports
field inpackage.json
linked to these files. This is an anti-pattern and was rightfully flagged by the "Are the Types Wrong?" tool as "masquerading as CJS". All of the ATTW checks now pass.
- Previously, this package shipped with only one variant of type declaration
files, and these files were only CommonJS-compatible, and the
- Remove chunk files (#4648).
- Previously, the build tool we used to generate JavaScript files extracted common code to "chunk" files. While this was intended to make this package more tree-shakeable, it also made debugging more difficult for our development teams. These chunk files are no longer present.
- Migrate from
@metamask/[email protected]
into@metamask/base-controller
: typesLegacyControllerStateConstraint
,RestrictedControllerMessengerConstraint
and type guard functionsisBaseController
,isBaseControllerV1
(#4581) - Add and export types
ControllerInstance
,BaseControllerInstance
,StateDeriverConstraint
,StateMetadataConstraint
,StatePropertyMetadataConstraint
,BaseControllerV1Instance
,ConfigConstraintV1
,StateConstraintV1
(#4581)
- BREAKING: Fix
StateMetadata
type so that it requires associated metadata for all optional and non-optional top-level state properties (#4612)- Fixes issue of runtime error being thrown during
BaseController
instantiation due to missing metadata for optional state properties.
- Fixes issue of runtime error being thrown during
- Bump TypeScript version to
~5.0.4
and setmoduleResolution
option toNode16
(#3645) - Bump
@metamask/utils
from^9.0.0
to^9.1.0
(#4529)
- Bump
@metamask/rpc-errors
from6.2.1
to^6.3.1
(#4516) - Bump
@metamask/utils
from^8.3.0
to^9.0.0
(#4516)
- BREAKING: Bump minimum Node version to 18.18 (#3611)
- Bump TypeScript version to
~4.9.5
(#4084)
- Fix
types
field inpackage.json
(#4047)
- BREAKING: Add ESM build (#3998)
- It's no longer possible to import files from
./dist
directly.
- It's no longer possible to import files from
- Add and export type
StateConstraint
, which is an alias forRecord<string, Json>
(#3949)- This type represents the narrowest supertype of the state of all controllers.
- Importing this type enables controllers to constrain state objects and types to be JSON-serializable without having to directly add
@metamask/utils
as a dependency.
- BREAKING: Narrow the return types of functions
getAnonymizedState<ControllerState>
andgetPersistentState<ControllerState>
fromRecord<string, Json>
toRecord<keyof ControllerState, Json>
. (#3949, #4040) - BREAKING: Align type-level and runtime behavior of
getRestricted
so that omitted or empty inputs consistently represent a set of empty allowlists (#4013)- If the
AllowedActions
andAllowedEvents
generic parameters are omitted, they are always assumed to benever
.- Previously, omission of these generic parameters resulted in the full allowlists for the controller being inferred as type constraints for the
allowedActions
andallowedEvents
function parameters.
- Previously, omission of these generic parameters resulted in the full allowlists for the controller being inferred as type constraints for the
- If the function parameters
allowedActions
andallowedEvents
are a non-empty array, their corresponding type names must be explicitly passed into generic parametersAllowedActions
andAllowedEvents
to avoid type errors.- This may cause some duplication of allowlists between type-level and value-level code.
- This requirement is only relevant for TypeScript code. A JavaScript consumer only needs to pass in the correct value-level function parameters. Because of this, these changes should not affect downstream JavaScript code, but may be disruptive to TypeScript code.
getRestricted
is still able to flagAllowedActions
andAllowedEvents
members that should not be included in the allowlists, based on theAction
andEvent
generic arguments passed into theControllerMessenger
instance.
- If the
- BREAKING: The
RestrictedControllerMessenger
class constructor now expectsallowedActions
andallowedEvents
as required options (#4013) - BREAKING: Add
string
as generic constraint to theName
generic parameter of the typesNamespacedBy
andNotNamespacedBy
(#4036) - BREAKING: The
getRestricted
method of theControllerMessenger
class now expects bothallowedActions
andallowedEvents
as required parameters.- An empty array is required if no allowed actions or events are desired.
- Convert interface
StatePropertyMetadata
into a type alias (#3949)
- BREAKING: Remove the deprecated
subscribe
class field fromBaseController
(#3949)- This property was used to differentiate between
BaseControllerV1
andBaseController
(v2) controllers. It is no longer used.
- This property was used to differentiate between
- BREAKING: Narrow the generic constraint of the
ControllerState
parameter fromRecord<string, unknown>
toRecord<string, Json>
for typesControllerGetStateAction
,ControllerStateChangeEvent
,ControllerActions
, andControllerEvents
(#3949) - BREAKING: Fix
BaseController
so that mutating state directly now results in a runtime error (#4011)- Directly modifying the state outside of an
update
call may lead to parts of the application being out of sync, because such modifications do not result in thestateChange
event being fired. - Instead of mutating the state of a controller after instantiation, consumers should either initialize that controller with the proper state via options or should use the
update
method to safely modify the state.
- Directly modifying the state outside of an
- BREAKING: Fix
subscribe
onControllerMessenger
andRestrictedControllerMessenger
to infer correct types forselector
arguments (#4012)- Previously, the types of the arguments that the
selector
function received would always be inferred asnever
, but now the types match those ofpublish
(the "event payload"). This means that you shouldn't need to add use type annotations or assertions to type theselector
arguments.
- Previously, the types of the arguments that the
- Bump
@metamask/utils
to^8.3.0
(#3769)
- Add
registerInitialEventPayload
toControllerMessenger
andRestrictedControllerMessenger
(#3697)- This allows registering an event payload function for an event, which has the benefit of ensuring the "subscription selector" feature works correctly the first time the event is fired after subscribing.
- Fix
subscribe
method selector support on first publish (#3697)- An event with a registered initial event payload function will work better with selectors, in that it will correctly compare with the initial selected state and return the previous value the first time it's published. Without this, the initial published event will always return
undefined
as the previous value.
- An event with a registered initial event payload function will work better with selectors, in that it will correctly compare with the initial selected state and return the previous value the first time it's published. Without this, the initial published event will always return
- Subscribers to the
stateChange
event of anyBaseControllerV2
-based controllers will now correctly handle the initial state change event (#3702)- Previously the initial state change would always result in this event firing, even for subscriptions with selectors where the selected value has not changed. Additionally, the
previousValue
returned was always set toundefined
the first time. BaseControllerV2
has been updated to correctly compare with the previous value even for the first state change. The returnedpreviousValue
is also now guaranteed to be correct even for the initial state change.
- Previously the initial state change would always result in this event firing, even for subscriptions with selectors where the selected value has not changed. Additionally, the
- Deprecate
subscribe
property fromBaseControllerV2
(#3590, #3698)- This property was used to differentiate between
BaseControllerV1
andBaseControllerV2
controllers. It is no longer used, so it has been marked as deprecated.
- This property was used to differentiate between
- Add
ControllerGetStateAction
andControllerStateChangeEvent
types (#1890, #2029) - Add
NamespacedName
type (#1890)- This is the narrowest supertype of all names defined within a given namespace.
- Add
NotNamespacedBy
type, which matches an action/event name if and only if it is not prefixed by a given namespace (#2051)
- BREAKING: Alter controller messenger
ActionHandler
type soAction
type parameter must satisfy (updated)ActionConstraint
(#1890) - BREAKING: Alter controller messenger
ExtractActionParameters
utility type soAction
type parameter must satisfy (updated)ActionConstraint
(#1890) - BREAKING: Alter controller messenger
ExtractEventHandler
utility type soEvent
type parameter must satisfyEventConstraint
(#1890) - BREAKING: Alter controller messenger
ExtractEventPayload
utility type soEvent
type parameter must satisfyEventConstraint
andEvent['payload']
must be an array (to match behavior ofExtractEventHandler
) (#1890) - BREAKING: Alter controller messenger
SelectorFunction
type so that its generic parameterArgs
is replaced byEvent
, which must satisfyEventConstraint
, and it returns a function whose arguments satisfy the event payload type specified byEvent
(#1890) - BREAKING:
BaseController
is now renamed toBaseControllerV1
and has been deprecated;BaseController
now points to what was previously calledBaseControllerV2
(#2078)- This should encourage use of
BaseController
v2 for new controllers going forward. - If your controller is importing
BaseControllerV2
, you will need to importBaseController
instead. - If your controller is still importing
BaseController
v1, you will need to import and useBaseControllerV1
instead. That said, please consider migrating your controller to v2.
- This should encourage use of
- BREAKING: The restricted controller messenger now allows calling all internal events and actions by default and prohibits explicitly allowlisting any of them (#2050, #2051)
- Previously internal events and actions were only usable if they were listed as "allowed" via the
allowedActions
orallowedEvents
options to theRestrictedControllerMessenger
constructor orControllerMessenger.getRestricted()
. Now this works implicitly. - In fact, attempting to allowlist any of them will raise a type error, as otherwise, it would be possible to specify a partial list of allowed actions or events, and that would be misleading, since all of them are allowed anyway.
- Previously internal events and actions were only usable if they were listed as "allowed" via the
- BREAKING: Rename
Namespaced
type toNamespacedBy
(#2051) - Alter controller messenger
ActionConstraint['handler']
type to remove usage ofany
(#1890)- This type is now defined as the universal supertype of all functions, meaning any function can be safely assigned as an action handler, regardless of argument types, number of arguments, or return value type.
- Bump
@metamask/utils
to ^8.2.0 (#1957)
- Bump dependency on
@metamask/utils
to ^8.1.0 (#1639)
- Update TypeScript to v4.8.x (#1718)
- There are no consumer-facing changes to this package. This version is a part of a synchronized release across all packages in our monorepo.
- When deriving state, skip properties with invalid metadata (#1529)
- The previous behavior was to throw an error
- An error is thrown in a timeout handler so that it can still be captured in the console, and by global unhandled error handlers.
- Update
@metamask/utils
to^6.2.0
(#1514)
- Prevent event publish from throwing error (#1475)
- The controller messenger will no longer throw when an event subscriber throws an error. Calls to
publish
(either within controllers or on a messenger instance directly) will no longer throw errors. - Errors are thrown in a timeout handler so that they can still be logged and captured.
- The controller messenger will no longer throw when an event subscriber throws an error. Calls to
- BREAKING: Bump to Node 16 (#1262)
- Replace
@metamask/controller-utils
dependency with@metamask/utils
(#1370)
- BREAKING: Remove
isomorphic-fetch
(#1106)- Consumers must now import
isomorphic-fetch
or another polyfill themselves if they are running in an environment withoutfetch
- Consumers must now import
- Relax dependency on
@metamask/controller-utils
(use^
instead of~
) (#998)
- Add
applyPatches
function to BaseControllerV2 (#980)
- Action and event handler types are now exported (#987)
- Update
update
function to expose patches (#980)
-
Initial release
-
As a result of converting our shared controllers repo into a monorepo (#831), we've created this package from select parts of
@metamask/controllers
v33.0.0, namely:src/BaseController.ts
src/BaseController.test.ts
src/BaseControllerV2.ts
src/BaseControllerV2.test.ts
src/ComposableController.ts
src/ComposableController.test.ts
src/ControllerMessenger.ts
src/ControllerMessenger.test.ts
All changes listed after this point were applied to this package following the monorepo conversion.
-