From f7f0b154f3121e25d91a55bf13718f7d834c8758 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 9 Dec 2024 20:55:23 -0330 Subject: [PATCH 1/2] chore: Rename `ControllerMessenger` to `Messenger` Rename the `ControllerMessenger` to `Messenger` so that it is clear it can be used for more than just controllers. This was decided by this ADR: https://github.com/MetaMask/decisions/blob/main/decisions/core/0001-messaging-non-controllers.md Previous names have been preserved as aliases to avoid making this a breaking change. Relates to #4538 --- packages/base-controller/CHANGELOG.md | 9 + .../src/BaseControllerV1.test.ts | 2 +- .../src/BaseControllerV2.test.ts | 4 +- .../base-controller/src/BaseControllerV2.ts | 4 +- ...lerMessenger.test.ts => Messenger.test.ts} | 311 ++++---- .../{ControllerMessenger.ts => Messenger.ts} | 55 +- ...er.test.ts => RestrictedMessenger.test.ts} | 662 ++++++++---------- ...lerMessenger.ts => RestrictedMessenger.ts} | 154 ++-- packages/base-controller/src/index.ts | 14 +- 9 files changed, 586 insertions(+), 629 deletions(-) rename packages/base-controller/src/{ControllerMessenger.test.ts => Messenger.test.ts} (58%) rename packages/base-controller/src/{ControllerMessenger.ts => Messenger.ts} (90%) rename packages/base-controller/src/{RestrictedControllerMessenger.test.ts => RestrictedMessenger.test.ts} (60%) rename packages/base-controller/src/{RestrictedControllerMessenger.ts => RestrictedMessenger.ts} (73%) diff --git a/packages/base-controller/CHANGELOG.md b/packages/base-controller/CHANGELOG.md index b8ce86fe45..374666e8fd 100644 --- a/packages/base-controller/CHANGELOG.md +++ b/packages/base-controller/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Rename `ControllerMessenger` to `Messenger` ([#5050](https://github.com/MetaMask/core/pull/5050)) + - `ControllerMessenger` has been renamed to `Messenger` + - `RestrictedControllerMessengerConstraint` has been renamed to `RestrictedMessengerConstraint` + - `RestrictedControllerMessenger` has been renamed to `RestrictedMessenger` + - The `RestrictedMessenger` constructor parameter `controllerMessenger` has been renamed to `messenger`, 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. + ## [7.0.2] ### Changed diff --git a/packages/base-controller/src/BaseControllerV1.test.ts b/packages/base-controller/src/BaseControllerV1.test.ts index f268f0f4a3..57a71b589f 100644 --- a/packages/base-controller/src/BaseControllerV1.test.ts +++ b/packages/base-controller/src/BaseControllerV1.test.ts @@ -16,7 +16,7 @@ import { countControllerStateMetadata, getCountMessenger, } from './BaseControllerV2.test'; -import { ControllerMessenger } from './ControllerMessenger'; +import { ControllerMessenger } from './Messenger'; const STATE = { name: 'foo' }; const CONFIG = { disabled: true }; diff --git a/packages/base-controller/src/BaseControllerV2.test.ts b/packages/base-controller/src/BaseControllerV2.test.ts index 9227505090..fc9f06516f 100644 --- a/packages/base-controller/src/BaseControllerV2.test.ts +++ b/packages/base-controller/src/BaseControllerV2.test.ts @@ -14,8 +14,8 @@ import { getPersistentState, isBaseController, } from './BaseControllerV2'; -import { ControllerMessenger } from './ControllerMessenger'; -import type { RestrictedControllerMessenger } from './RestrictedControllerMessenger'; +import { ControllerMessenger } from './Messenger'; +import type { RestrictedControllerMessenger } from './RestrictedMessenger'; export const countControllerName = 'CountController'; diff --git a/packages/base-controller/src/BaseControllerV2.ts b/packages/base-controller/src/BaseControllerV2.ts index 355d156689..1dd2bb05b4 100644 --- a/packages/base-controller/src/BaseControllerV2.ts +++ b/packages/base-controller/src/BaseControllerV2.ts @@ -6,11 +6,11 @@ import type { BaseControllerV1Instance, StateConstraint as StateConstraintV1, } from './BaseControllerV1'; -import type { ActionConstraint, EventConstraint } from './ControllerMessenger'; +import type { ActionConstraint, EventConstraint } from './Messenger'; import type { RestrictedControllerMessenger, RestrictedControllerMessengerConstraint, -} from './RestrictedControllerMessenger'; +} from './RestrictedMessenger'; enablePatches(); diff --git a/packages/base-controller/src/ControllerMessenger.test.ts b/packages/base-controller/src/Messenger.test.ts similarity index 58% rename from packages/base-controller/src/ControllerMessenger.test.ts rename to packages/base-controller/src/Messenger.test.ts index 6dec60d1fb..fe00e91e84 100644 --- a/packages/base-controller/src/ControllerMessenger.test.ts +++ b/packages/base-controller/src/Messenger.test.ts @@ -1,30 +1,29 @@ import type { Patch } from 'immer'; import * as sinon from 'sinon'; -import { ControllerMessenger } from './ControllerMessenger'; +import { Messenger } from './Messenger'; -describe('ControllerMessenger', () => { +describe('Messenger', () => { afterEach(() => { sinon.restore(); }); it('should allow registering and calling an action handler', () => { type CountAction = { type: 'count'; handler: (increment: number) => void }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); let count = 0; - controllerMessenger.registerActionHandler('count', (increment: number) => { + messenger.registerActionHandler('count', (increment: number) => { count += increment; }); - controllerMessenger.call('count', 1); + messenger.call('count', 1); expect(count).toBe(1); }); it('should allow registering and calling multiple different action handlers', () => { - // These 'Other' types are included to demonstrate that controller messenger - // generics can indeed be unions of actions and events from different - // controllers. + // These 'Other' types are included to demonstrate that messenger generics can indeed be unions + // of actions and events from different modules. type GetOtherState = { type: `OtherController:getState`; handler: () => { stuff: string }; @@ -38,41 +37,35 @@ describe('ControllerMessenger', () => { type MessageAction = | { type: 'concat'; handler: (message: string) => void } | { type: 'reset'; handler: (initialMessage: string) => void }; - const controllerMessenger = new ControllerMessenger< + const messenger = new Messenger< MessageAction | GetOtherState, OtherStateChange >(); let message = ''; - controllerMessenger.registerActionHandler( - 'reset', - (initialMessage: string) => { - message = initialMessage; - }, - ); + messenger.registerActionHandler('reset', (initialMessage: string) => { + message = initialMessage; + }); - controllerMessenger.registerActionHandler('concat', (s: string) => { + messenger.registerActionHandler('concat', (s: string) => { message += s; }); - controllerMessenger.call('reset', 'hello'); - controllerMessenger.call('concat', ', world'); + messenger.call('reset', 'hello'); + messenger.call('concat', ', world'); expect(message).toBe('hello, world'); }); it('should allow registering and calling an action handler with no parameters', () => { type IncrementAction = { type: 'increment'; handler: () => void }; - const controllerMessenger = new ControllerMessenger< - IncrementAction, - never - >(); + const messenger = new Messenger(); let count = 0; - controllerMessenger.registerActionHandler('increment', () => { + messenger.registerActionHandler('increment', () => { count += 1; }); - controllerMessenger.call('increment'); + messenger.call('increment'); expect(count).toBe(1); }); @@ -82,98 +75,98 @@ describe('ControllerMessenger', () => { type: 'message'; handler: (to: string, message: string) => void; }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const messages: Record = {}; - controllerMessenger.registerActionHandler('message', (to, message) => { + messenger.registerActionHandler('message', (to, message) => { messages[to] = message; }); - controllerMessenger.call('message', '0x123', 'hello'); + messenger.call('message', '0x123', 'hello'); expect(messages['0x123']).toBe('hello'); }); it('should allow registering and calling an action handler with a return value', () => { type AddAction = { type: 'add'; handler: (a: number, b: number) => number }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); - controllerMessenger.registerActionHandler('add', (a, b) => { + messenger.registerActionHandler('add', (a, b) => { return a + b; }); - const result = controllerMessenger.call('add', 5, 10); + const result = messenger.call('add', 5, 10); expect(result).toBe(15); }); it('should not allow registering multiple action handlers under the same name', () => { type PingAction = { type: 'ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); - controllerMessenger.registerActionHandler('ping', () => undefined); + messenger.registerActionHandler('ping', () => undefined); expect(() => { - controllerMessenger.registerActionHandler('ping', () => undefined); + messenger.registerActionHandler('ping', () => undefined); }).toThrow('A handler for ping has already been registered'); }); it('should throw when calling unregistered action', () => { type PingAction = { type: 'ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); expect(() => { - controllerMessenger.call('ping'); + messenger.call('ping'); }).toThrow('A handler for ping has not been registered'); }); it('should throw when calling an action that has been unregistered', () => { type PingAction = { type: 'ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); expect(() => { - controllerMessenger.call('ping'); + messenger.call('ping'); }).toThrow('A handler for ping has not been registered'); let pingCount = 0; - controllerMessenger.registerActionHandler('ping', () => { + messenger.registerActionHandler('ping', () => { pingCount += 1; }); - controllerMessenger.unregisterActionHandler('ping'); + messenger.unregisterActionHandler('ping'); expect(() => { - controllerMessenger.call('ping'); + messenger.call('ping'); }).toThrow('A handler for ping has not been registered'); expect(pingCount).toBe(0); }); it('should throw when calling an action after actions have been reset', () => { type PingAction = { type: 'ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); expect(() => { - controllerMessenger.call('ping'); + messenger.call('ping'); }).toThrow('A handler for ping has not been registered'); let pingCount = 0; - controllerMessenger.registerActionHandler('ping', () => { + messenger.registerActionHandler('ping', () => { pingCount += 1; }); - controllerMessenger.clearActions(); + messenger.clearActions(); expect(() => { - controllerMessenger.call('ping'); + messenger.call('ping'); }).toThrow('A handler for ping has not been registered'); expect(pingCount).toBe(0); }); it('should publish event to subscriber', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('message', handler); - controllerMessenger.publish('message', 'hello'); + messenger.subscribe('message', handler); + messenger.publish('message', 'hello'); expect(handler.calledWithExactly('hello')).toBe(true); expect(handler.callCount).toBe(1); @@ -183,15 +176,15 @@ describe('ControllerMessenger', () => { type MessageEvent = | { type: 'message'; payload: [string] } | { type: 'ping'; payload: [] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const messageHandler = sinon.stub(); const pingHandler = sinon.stub(); - controllerMessenger.subscribe('message', messageHandler); - controllerMessenger.subscribe('ping', pingHandler); + messenger.subscribe('message', messageHandler); + messenger.subscribe('ping', pingHandler); - controllerMessenger.publish('message', 'hello'); - controllerMessenger.publish('ping'); + messenger.publish('message', 'hello'); + messenger.publish('ping'); expect(messageHandler.calledWithExactly('hello')).toBe(true); expect(messageHandler.callCount).toBe(1); @@ -201,11 +194,11 @@ describe('ControllerMessenger', () => { it('should publish event with no payload to subscriber', () => { type PingEvent = { type: 'ping'; payload: [] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('ping', handler); - controllerMessenger.publish('ping'); + messenger.subscribe('ping', handler); + messenger.publish('ping'); expect(handler.calledWithExactly()).toBe(true); expect(handler.callCount).toBe(1); @@ -213,11 +206,11 @@ describe('ControllerMessenger', () => { it('should publish event with multiple payload parameters to subscriber', () => { type MessageEvent = { type: 'message'; payload: [string, string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('message', handler); - controllerMessenger.publish('message', 'hello', 'there'); + messenger.subscribe('message', handler); + messenger.publish('message', 'hello', 'there'); expect(handler.calledWithExactly('hello', 'there')).toBe(true); expect(handler.callCount).toBe(1); @@ -225,12 +218,12 @@ describe('ControllerMessenger', () => { it('should publish event once to subscriber even if subscribed multiple times', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('message', handler); - controllerMessenger.subscribe('message', handler); - controllerMessenger.publish('message', 'hello'); + messenger.subscribe('message', handler); + messenger.subscribe('message', handler); + messenger.publish('message', 'hello'); expect(handler.calledWithExactly('hello')).toBe(true); expect(handler.callCount).toBe(1); @@ -238,13 +231,13 @@ describe('ControllerMessenger', () => { it('should publish event to many subscribers', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler1 = sinon.stub(); const handler2 = sinon.stub(); - controllerMessenger.subscribe('message', handler1); - controllerMessenger.subscribe('message', handler2); - controllerMessenger.publish('message', 'hello'); + messenger.subscribe('message', handler1); + messenger.subscribe('message', handler2); + messenger.publish('message', 'hello'); expect(handler1.calledWithExactly('hello')).toBe(true); expect(handler1.callCount).toBe(1); @@ -262,23 +255,16 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - controllerMessenger.registerInitialEventPayload({ + const messenger = new Messenger(); + messenger.registerInitialEventPayload({ eventType: 'complexMessage', getPayload: () => [state], }); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.propA, - ); + messenger.subscribe('complexMessage', handler, (obj) => obj.propA); state.propA += 1; - controllerMessenger.publish('complexMessage', state); + messenger.publish('complexMessage', state); expect(handler.getCall(0)?.args).toStrictEqual([2, 1]); expect(handler.callCount).toBe(1); @@ -293,22 +279,15 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - controllerMessenger.registerInitialEventPayload({ + const messenger = new Messenger(); + messenger.registerInitialEventPayload({ eventType: 'complexMessage', getPayload: () => [state], }); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.propA, - ); + messenger.subscribe('complexMessage', handler, (obj) => obj.propA); - controllerMessenger.publish('complexMessage', state); + messenger.publish('complexMessage', state); expect(handler.callCount).toBe(0); }); @@ -324,19 +303,12 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.propA, - ); + messenger.subscribe('complexMessage', handler, (obj) => obj.propA); state.propA += 1; - controllerMessenger.publish('complexMessage', state); + messenger.publish('complexMessage', state); expect(handler.getCall(0)?.args).toStrictEqual([2, undefined]); expect(handler.callCount).toBe(1); @@ -351,18 +323,11 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.propA, - ); + messenger.subscribe('complexMessage', handler, (obj) => obj.propA); - controllerMessenger.publish('complexMessage', state); + messenger.publish('complexMessage', state); expect(handler.getCall(0)?.args).toStrictEqual([1, undefined]); expect(handler.callCount).toBe(1); @@ -377,18 +342,11 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.propA, - ); + messenger.subscribe('complexMessage', handler, (obj) => obj.propA); - controllerMessenger.publish('complexMessage', state); + messenger.publish('complexMessage', state); expect(handler.callCount).toBe(0); }); @@ -400,19 +358,12 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.prop1, - ); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); - controllerMessenger.publish('complexMessage', { prop1: 'z', prop2: 'b' }); + messenger.subscribe('complexMessage', handler, (obj) => obj.prop1); + messenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); + messenger.publish('complexMessage', { prop1: 'z', prop2: 'b' }); expect(handler.getCall(0).calledWithExactly('a', undefined)).toBe(true); expect(handler.getCall(1).calledWithExactly('z', 'a')).toBe(true); @@ -424,18 +375,11 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.prop1, - ); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); + messenger.subscribe('complexMessage', handler, (obj) => obj.prop1); + messenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); expect(handler.calledWithExactly('a', undefined)).toBe(true); expect(handler.callCount).toBe(1); @@ -446,19 +390,12 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe( - 'complexMessage', - handler, - (obj) => obj.prop1, - ); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop3: 'c' }); + messenger.subscribe('complexMessage', handler, (obj) => obj.prop1); + messenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); + messenger.publish('complexMessage', { prop1: 'a', prop3: 'c' }); expect(handler.calledWithExactly('a', undefined)).toBe(true); expect(handler.callCount).toBe(1); @@ -470,15 +407,15 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler1 = sinon.stub(); const handler2 = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.prop1); - controllerMessenger.subscribe('complexMessage', handler1, selector); - controllerMessenger.subscribe('complexMessage', handler2, selector); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop3: 'c' }); + messenger.subscribe('complexMessage', handler1, selector); + messenger.subscribe('complexMessage', handler2, selector); + messenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); + messenger.publish('complexMessage', { prop1: 'a', prop3: 'c' }); expect(handler1.calledWithExactly('a', undefined)).toBe(true); expect(handler1.callCount).toBe(1); @@ -505,12 +442,12 @@ describe('ControllerMessenger', () => { it('should throw subscriber errors in a timeout', () => { const setTimeoutStub = sinon.stub(globalThis, 'setTimeout'); type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub().throws(() => new Error('Example error')); - controllerMessenger.subscribe('message', handler); + messenger.subscribe('message', handler); - expect(() => controllerMessenger.publish('message', 'hello')).not.toThrow(); + expect(() => messenger.publish('message', 'hello')).not.toThrow(); expect(setTimeoutStub.callCount).toBe(1); const onTimeout = setTimeoutStub.firstCall.args[0]; expect(() => onTimeout()).toThrow('Example error'); @@ -519,14 +456,14 @@ describe('ControllerMessenger', () => { it('should continue calling subscribers when one throws', () => { const setTimeoutStub = sinon.stub(globalThis, 'setTimeout'); type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler1 = sinon.stub().throws(() => new Error('Example error')); const handler2 = sinon.stub(); - controllerMessenger.subscribe('message', handler1); - controllerMessenger.subscribe('message', handler2); + messenger.subscribe('message', handler1); + messenger.subscribe('message', handler2); - expect(() => controllerMessenger.publish('message', 'hello')).not.toThrow(); + expect(() => messenger.publish('message', 'hello')).not.toThrow(); expect(handler1.calledWithExactly('hello')).toBe(true); expect(handler1.callCount).toBe(1); @@ -539,12 +476,12 @@ describe('ControllerMessenger', () => { it('should not call subscriber after unsubscribing', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('message', handler); - controllerMessenger.unsubscribe('message', handler); - controllerMessenger.publish('message', 'hello'); + messenger.subscribe('message', handler); + messenger.unsubscribe('message', handler); + messenger.publish('message', 'hello'); expect(handler.callCount).toBe(0); }); @@ -554,13 +491,13 @@ describe('ControllerMessenger', () => { type: 'complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.prop1); - controllerMessenger.subscribe('complexMessage', handler, selector); - controllerMessenger.unsubscribe('complexMessage', handler); - controllerMessenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); + messenger.subscribe('complexMessage', handler, selector); + messenger.unsubscribe('complexMessage', handler); + messenger.publish('complexMessage', { prop1: 'a', prop2: 'b' }); expect(handler.callCount).toBe(0); expect(selector.callCount).toBe(0); @@ -568,56 +505,54 @@ describe('ControllerMessenger', () => { it('should throw when unsubscribing when there are no subscriptions', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - expect(() => controllerMessenger.unsubscribe('message', handler)).toThrow( + expect(() => messenger.unsubscribe('message', handler)).toThrow( 'Subscription not found for event: message', ); }); it('should throw when unsubscribing a handler that is not subscribed', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler1 = sinon.stub(); const handler2 = sinon.stub(); - controllerMessenger.subscribe('message', handler1); + messenger.subscribe('message', handler1); - expect(() => controllerMessenger.unsubscribe('message', handler2)).toThrow( + expect(() => messenger.unsubscribe('message', handler2)).toThrow( 'Subscription not found for event: message', ); }); it('should not call subscriber after clearing event subscriptions', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('message', handler); - controllerMessenger.clearEventSubscriptions('message'); - controllerMessenger.publish('message', 'hello'); + messenger.subscribe('message', handler); + messenger.clearEventSubscriptions('message'); + messenger.publish('message', 'hello'); expect(handler.callCount).toBe(0); }); it('should not throw when clearing event that has no subscriptions', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); - expect(() => - controllerMessenger.clearEventSubscriptions('message'), - ).not.toThrow(); + expect(() => messenger.clearEventSubscriptions('message')).not.toThrow(); }); it('should not call subscriber after resetting subscriptions', () => { type MessageEvent = { type: 'message'; payload: [string] }; - const controllerMessenger = new ControllerMessenger(); + const messenger = new Messenger(); const handler = sinon.stub(); - controllerMessenger.subscribe('message', handler); - controllerMessenger.clearSubscriptions(); - controllerMessenger.publish('message', 'hello'); + messenger.subscribe('message', handler); + messenger.clearSubscriptions(); + messenger.publish('message', 'hello'); expect(handler.callCount).toBe(0); }); diff --git a/packages/base-controller/src/ControllerMessenger.ts b/packages/base-controller/src/Messenger.ts similarity index 90% rename from packages/base-controller/src/ControllerMessenger.ts rename to packages/base-controller/src/Messenger.ts index ea524bd3e6..fbc225efb9 100644 --- a/packages/base-controller/src/ControllerMessenger.ts +++ b/packages/base-controller/src/Messenger.ts @@ -1,4 +1,4 @@ -import { RestrictedControllerMessenger } from './RestrictedControllerMessenger'; +import { RestrictedMessenger } from './RestrictedMessenger'; export type ActionHandler< Action extends ActionConstraint, @@ -114,16 +114,16 @@ type NarrowToAllowed = Name extends { : never; /** - * A messaging system for controllers. + * A message broker for "actions" and "events". * - * The controller messenger allows registering functions as 'actions' that can be called elsewhere, + * The messenger allows registering functions as 'actions' that can be called elsewhere, * and it allows publishing and subscribing to events. Both actions and events are identified by * unique strings. * * @template Action - A type union of all Action types. * @template Event - A type union of all Event types. */ -export class ControllerMessenger< +export class Messenger< Action extends ActionConstraint, Event extends EventConstraint, > { @@ -399,30 +399,30 @@ export class ControllerMessenger< } /** - * Get a restricted controller messenger + * Get a restricted messenger * - * Returns a wrapper around the controller messenger instance that restricts access to actions - * and events. The provided allowlists grant the ability to call the listed actions and subscribe - * to the listed events. The "name" provided grants ownership of any actions and events under - * that namespace. Ownership allows registering actions and publishing events, as well as + * Returns a wrapper around the messenger instance that restricts access to actions and events. + * The provided allowlists grant the ability to call the listed actions and subscribe to the + * listed events. The "name" provided grants ownership of any actions and events under that + * namespace. Ownership allows registering actions and publishing events, as well as * unregistering actions and clearing event subscriptions. * * @param options - Controller messenger options. * @param options.name - The name of the thing this messenger will be handed to (e.g. the * controller name). This grants "ownership" of actions and events under this namespace to the - * restricted controller messenger returned. - * @param options.allowedActions - The list of actions that this restricted controller messenger - * should be alowed to call. - * @param options.allowedEvents - The list of events that this restricted controller messenger - * should be allowed to subscribe to. - * @template Namespace - The namespace for this messenger. Typically this is the name of the controller or + * restricted messenger returned. + * @param options.allowedActions - The list of actions that this restricted messenger should be + * allowed to call. + * @param options.allowedEvents - The list of events that this restricted messenger should be + * allowed to subscribe to. + * @template Namespace - The namespace for this messenger. Typically this is the name of the * module that this messenger has been created for. The authority to publish events and register * actions under this namespace is granted to this restricted messenger instance. * @template AllowedAction - A type union of the 'type' string for any allowed actions. * This must not include internal actions that are in the messenger's namespace. * @template AllowedEvent - A type union of the 'type' string for any allowed events. * This must not include internal events that are in the messenger's namespace. - * @returns The restricted controller messenger. + * @returns The restricted messenger. */ getRestricted< Namespace extends string, @@ -442,7 +442,7 @@ export class ControllerMessenger< Namespace, Extract >[]; - }): RestrictedControllerMessenger< + }): RestrictedMessenger< Namespace, | NarrowToNamespace | NarrowToAllowed, @@ -450,11 +450,28 @@ export class ControllerMessenger< AllowedAction, AllowedEvent > { - return new RestrictedControllerMessenger({ - controllerMessenger: this, + return new RestrictedMessenger({ + messenger: this, name, allowedActions, allowedEvents, }); } } + +/** + * A message broker for "actions" and "events". + * + * The messenger allows registering functions as 'actions' that can be called elsewhere, + * and it allows publishing and subscribing to events. Both actions and events are identified by + * unique strings. + * + * @template Action - A type union of all Action types. + * @template Event - A type union of all Event types. + * @deprecated This has been renamed to `Messenger`. + */ +export const ControllerMessenger = Messenger; +export type ControllerMessenger< + Action extends ActionConstraint, + Event extends EventConstraint, +> = Messenger; diff --git a/packages/base-controller/src/RestrictedControllerMessenger.test.ts b/packages/base-controller/src/RestrictedMessenger.test.ts similarity index 60% rename from packages/base-controller/src/RestrictedControllerMessenger.test.ts rename to packages/base-controller/src/RestrictedMessenger.test.ts index e4273e6729..c0c2a66115 100644 --- a/packages/base-controller/src/RestrictedControllerMessenger.test.ts +++ b/packages/base-controller/src/RestrictedMessenger.test.ts @@ -1,28 +1,121 @@ import * as sinon from 'sinon'; -import { ControllerMessenger } from './ControllerMessenger'; +import { Messenger } from './Messenger'; +import { RestrictedMessenger } from './RestrictedMessenger'; + +describe('RestrictedMessenger', () => { + describe('constructor', () => { + it('should throw if no messenger is provided', () => { + expect( + () => + new RestrictedMessenger({ + name: 'Test', + allowedActions: [], + allowedEvents: [], + }), + ).toThrow('Messenger not provided'); + }); + + it('should throw if both controllerMessenger and messenger are provided', () => { + const messenger = new Messenger(); + + expect( + () => + new RestrictedMessenger({ + controllerMessenger: messenger, + messenger, + name: 'Test', + allowedActions: [], + allowedEvents: [], + }), + ).toThrow( + `Both messenger properties provided. Provide message using only 'messenger' option, 'controllerMessenger' is deprecated`, + ); + }); + + it('should accept messenger parameter', () => { + type CountAction = { + type: 'CountController:count'; + handler: (increment: number) => void; + }; + const messenger = new Messenger(); + const restrictedMessenger = new RestrictedMessenger< + 'CountController', + CountAction, + never, + never, + never + >({ + messenger, + name: 'CountController', + allowedActions: [], + allowedEvents: [], + }); + + let count = 0; + restrictedMessenger.registerActionHandler( + 'CountController:count', + (increment: number) => { + count += increment; + }, + ); + restrictedMessenger.call('CountController:count', 1); + + expect(count).toBe(1); + }); + + it('should accept controllerMessenger parameter', () => { + type CountAction = { + type: 'CountController:count'; + handler: (increment: number) => void; + }; + const messenger = new Messenger(); + const restrictedMessenger = new RestrictedMessenger< + 'CountController', + CountAction, + never, + never, + never + >({ + controllerMessenger: messenger, + name: 'CountController', + allowedActions: [], + allowedEvents: [], + }); + + let count = 0; + restrictedMessenger.registerActionHandler( + 'CountController:count', + (increment: number) => { + count += increment; + }, + ); + restrictedMessenger.call('CountController:count', 1); + + expect(count).toBe(1); + }); + }); -describe('RestrictedControllerMessenger', () => { it('should allow registering and calling an action handler', () => { type CountAction = { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'CountController', allowedActions: [], allowedEvents: [], }); let count = 0; - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'CountController:count', (increment: number) => { count += increment; }, ); - restrictedControllerMessenger.call('CountController:count', 1); + restrictedMessenger.call('CountController:count', 1); expect(count).toBe(1); }); @@ -34,30 +127,30 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:reset'; handler: (initialMessage: string) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); let message = ''; - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'MessageController:reset', (initialMessage: string) => { message = initialMessage; }, ); - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'MessageController:concat', (s: string) => { message += s; }, ); - restrictedControllerMessenger.call('MessageController:reset', 'hello'); - restrictedControllerMessenger.call('MessageController:concat', ', world'); + restrictedMessenger.call('MessageController:reset', 'hello'); + restrictedMessenger.call('MessageController:concat', ', world'); expect(message).toBe('hello, world'); }); @@ -67,24 +160,21 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:increment'; handler: () => void; }; - const controllerMessenger = new ControllerMessenger< - IncrementAction, - never - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'CountController', allowedActions: [], allowedEvents: [], }); let count = 0; - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'CountController:increment', () => { count += 1; }, ); - restrictedControllerMessenger.call('CountController:increment'); + restrictedMessenger.call('CountController:increment'); expect(count).toBe(1); }); @@ -94,26 +184,22 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; handler: (to: string, message: string) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const messages: Record = {}; - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'MessageController:message', (to, message) => { messages[to] = message; }, ); - restrictedControllerMessenger.call( - 'MessageController:message', - '0x123', - 'hello', - ); + restrictedMessenger.call('MessageController:message', '0x123', 'hello'); expect(messages['0x123']).toBe('hello'); }); @@ -123,44 +209,37 @@ describe('RestrictedControllerMessenger', () => { type: 'MathController:add'; handler: (a: number, b: number) => number; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MathController', allowedActions: [], allowedEvents: [], }); - restrictedControllerMessenger.registerActionHandler( - 'MathController:add', - (a, b) => { - return a + b; - }, - ); - const result = restrictedControllerMessenger.call( - 'MathController:add', - 5, - 10, - ); + restrictedMessenger.registerActionHandler('MathController:add', (a, b) => { + return a + b; + }); + const result = restrictedMessenger.call('MathController:add', 5, 10); expect(result).toBe(15); }); it('should not allow registering multiple action handlers under the same name', () => { type CountAction = { type: 'PingController:ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'PingController', allowedActions: [], allowedEvents: [], }); - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'PingController:ping', () => undefined, ); expect(() => { - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'PingController:ping', () => undefined, ); @@ -172,15 +251,15 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'CountController', allowedActions: [], allowedEvents: [], }); expect(() => { - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( // @ts-expect-error: suppressing to test runtime error handling 'OtherController:other', () => undefined, @@ -195,15 +274,15 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); expect(() => { - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( // @ts-expect-error: suppressing to test runtime error handling 'OtherController:other', () => undefined, @@ -220,18 +299,15 @@ describe('RestrictedControllerMessenger', () => { type: 'OtherController:other'; payload: [unknown]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent | OtherEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: ['OtherController:other'], }); expect(() => { - restrictedControllerMessenger.publish( + restrictedMessenger.publish( // @ts-expect-error: suppressing to test runtime error handling 'OtherController:other', () => undefined, @@ -246,15 +322,15 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); expect(() => { - restrictedControllerMessenger.unsubscribe( + restrictedMessenger.unsubscribe( // @ts-expect-error: suppressing to test runtime error handling 'OtherController:other', () => undefined, @@ -271,18 +347,15 @@ describe('RestrictedControllerMessenger', () => { type: 'OtherController:other'; payload: [unknown]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent | OtherEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: ['OtherController:other'], }); expect(() => { - restrictedControllerMessenger.clearEventSubscriptions( + restrictedMessenger.clearEventSubscriptions( // @ts-expect-error: suppressing to test runtime error handling 'OtherController:other', ); @@ -294,8 +367,8 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'PingController', allowedActions: [], allowedEvents: [], @@ -303,7 +376,7 @@ describe('RestrictedControllerMessenger', () => { expect(() => { // @ts-expect-error suppressing to test runtime error handling - restrictedControllerMessenger.call('CountController:count'); + restrictedMessenger.call('CountController:count'); }).toThrow('Action missing from allow list: CountController:count'); }); @@ -312,8 +385,8 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted< + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted< 'PingController', CountAction['type'] >({ @@ -323,7 +396,7 @@ describe('RestrictedControllerMessenger', () => { }); expect(() => { - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( // @ts-expect-error suppressing to test runtime error handling 'CountController:count', () => undefined, @@ -338,8 +411,8 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted< + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted< 'PingController', CountAction['type'] >({ @@ -348,7 +421,7 @@ describe('RestrictedControllerMessenger', () => { allowedEvents: [], }); expect(() => { - restrictedControllerMessenger.unregisterActionHandler( + restrictedMessenger.unregisterActionHandler( // @ts-expect-error suppressing to test runtime error handling 'CountController:count', ); @@ -359,45 +432,40 @@ describe('RestrictedControllerMessenger', () => { it('should throw when calling unregistered action', () => { type PingAction = { type: 'PingController:ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'PingController', allowedActions: [], allowedEvents: [], }); expect(() => { - restrictedControllerMessenger.call('PingController:ping'); + restrictedMessenger.call('PingController:ping'); }).toThrow('A handler for PingController:ping has not been registered'); }); it('should throw when calling an action that has been unregistered', () => { type PingAction = { type: 'PingController:ping'; handler: () => void }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'PingController', allowedActions: [], allowedEvents: [], }); expect(() => { - restrictedControllerMessenger.call('PingController:ping'); + restrictedMessenger.call('PingController:ping'); }).toThrow('A handler for PingController:ping has not been registered'); let pingCount = 0; - restrictedControllerMessenger.registerActionHandler( - 'PingController:ping', - () => { - pingCount += 1; - }, - ); + restrictedMessenger.registerActionHandler('PingController:ping', () => { + pingCount += 1; + }); - restrictedControllerMessenger.unregisterActionHandler( - 'PingController:ping', - ); + restrictedMessenger.unregisterActionHandler('PingController:ping'); expect(() => { - restrictedControllerMessenger.call('PingController:ping'); + restrictedMessenger.call('PingController:ping'); }).toThrow('A handler for PingController:ping has not been registered'); expect(pingCount).toBe(0); }); @@ -407,15 +475,15 @@ describe('RestrictedControllerMessenger', () => { type: 'OtherController:complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); expect(() => - restrictedControllerMessenger.registerInitialEventPayload({ + restrictedMessenger.registerInitialEventPayload({ // @ts-expect-error suppressing to test runtime error handling eventType: 'OtherController:complexMessage', // @ts-expect-error suppressing to test runtime error handling @@ -431,19 +499,16 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.subscribe('MessageController:message', handler); + restrictedMessenger.publish('MessageController:message', 'hello'); expect(handler.calledWithExactly('hello')).toBe(true); expect(handler.callCount).toBe(1); @@ -459,32 +524,26 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); - restrictedControllerMessenger.registerInitialEventPayload({ + restrictedMessenger.registerInitialEventPayload({ eventType: 'MessageController:complexMessage', getPayload: () => [state], }); const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.propA); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); state.propA += 1; - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - state, - ); + restrictedMessenger.publish('MessageController:complexMessage', state); expect(handler.getCall(0)?.args).toStrictEqual([2, 1]); expect(handler.callCount).toBe(1); @@ -499,31 +558,25 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); - restrictedControllerMessenger.registerInitialEventPayload({ + restrictedMessenger.registerInitialEventPayload({ eventType: 'MessageController:complexMessage', getPayload: () => [state], }); const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.propA); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - state, - ); + restrictedMessenger.publish('MessageController:complexMessage', state); expect(handler.callCount).toBe(0); }); @@ -539,28 +592,22 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.propA); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); state.propA += 1; - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - state, - ); + restrictedMessenger.publish('MessageController:complexMessage', state); expect(handler.getCall(0)?.args).toStrictEqual([2, undefined]); expect(handler.callCount).toBe(1); @@ -575,27 +622,21 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.propA); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - state, - ); + restrictedMessenger.publish('MessageController:complexMessage', state); expect(handler.getCall(0)?.args).toStrictEqual([1, undefined]); expect(handler.callCount).toBe(1); @@ -610,27 +651,21 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [typeof state]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.propA); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - state, - ); + restrictedMessenger.publish('MessageController:complexMessage', state); expect(handler.callCount).toBe(0); }); @@ -642,11 +677,8 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -654,25 +686,19 @@ describe('RestrictedControllerMessenger', () => { const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.prop1); - controllerMessenger.subscribe( + messenger.subscribe( 'MessageController:complexMessage', handler, selector, ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - { - prop1: 'a', - prop2: 'b', - }, - ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - { - prop1: 'z', - prop2: 'b', - }, - ); + restrictedMessenger.publish('MessageController:complexMessage', { + prop1: 'a', + prop2: 'b', + }); + restrictedMessenger.publish('MessageController:complexMessage', { + prop1: 'z', + prop2: 'b', + }); expect(handler.getCall(0).calledWithExactly('a', undefined)).toBe(true); expect(handler.getCall(1).calledWithExactly('z', 'a')).toBe(true); @@ -684,11 +710,8 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -696,18 +719,15 @@ describe('RestrictedControllerMessenger', () => { const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.prop1); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - { - prop1: 'a', - prop2: 'b', - }, - ); + restrictedMessenger.publish('MessageController:complexMessage', { + prop1: 'a', + prop2: 'b', + }); expect(handler.calledWithExactly('a', undefined)).toBe(true); expect(handler.callCount).toBe(1); @@ -718,11 +738,8 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:complexMessage'; payload: [Record]; }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent - >(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -730,25 +747,19 @@ describe('RestrictedControllerMessenger', () => { const handler = sinon.stub(); const selector = sinon.fake((obj: Record) => obj.prop1); - restrictedControllerMessenger.subscribe( + restrictedMessenger.subscribe( 'MessageController:complexMessage', handler, selector, ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - { - prop1: 'a', - prop2: 'b', - }, - ); - restrictedControllerMessenger.publish( - 'MessageController:complexMessage', - { - prop1: 'a', - prop3: 'c', - }, - ); + restrictedMessenger.publish('MessageController:complexMessage', { + prop1: 'a', + prop2: 'b', + }); + restrictedMessenger.publish('MessageController:complexMessage', { + prop1: 'a', + prop3: 'c', + }); expect(handler.calledWithExactly('a', undefined)).toBe(true); expect(handler.callCount).toBe(1); @@ -759,8 +770,8 @@ describe('RestrictedControllerMessenger', () => { type MessageEvent = | { type: 'MessageController:message'; payload: [string] } | { type: 'MessageController:ping'; payload: [] }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -768,18 +779,12 @@ describe('RestrictedControllerMessenger', () => { const messageHandler = sinon.stub(); const pingHandler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - messageHandler, - ); + restrictedMessenger.subscribe('MessageController:message', messageHandler); - restrictedControllerMessenger.subscribe( - 'MessageController:ping', - pingHandler, - ); + restrictedMessenger.subscribe('MessageController:ping', pingHandler); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); - restrictedControllerMessenger.publish('MessageController:ping'); + restrictedMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.publish('MessageController:ping'); expect(messageHandler.calledWithExactly('hello')).toBe(true); expect(messageHandler.callCount).toBe(1); @@ -789,16 +794,16 @@ describe('RestrictedControllerMessenger', () => { it('should publish event with no payload to subscriber', () => { type PingEvent = { type: 'PingController:ping'; payload: [] }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'PingController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe('PingController:ping', handler); - restrictedControllerMessenger.publish('PingController:ping'); + restrictedMessenger.subscribe('PingController:ping', handler); + restrictedMessenger.publish('PingController:ping'); expect(handler.calledWithExactly()).toBe(true); expect(handler.callCount).toBe(1); @@ -809,24 +814,17 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string, string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); + restrictedMessenger.subscribe('MessageController:message', handler); - restrictedControllerMessenger.publish( - 'MessageController:message', - 'hello', - 'there', - ); + restrictedMessenger.publish('MessageController:message', 'hello', 'there'); expect(handler.calledWithExactly('hello', 'there')).toBe(true); expect(handler.callCount).toBe(1); @@ -837,24 +835,18 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); + restrictedMessenger.subscribe('MessageController:message', handler); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.subscribe('MessageController:message', handler); + restrictedMessenger.publish('MessageController:message', 'hello'); expect(handler.calledWithExactly('hello')).toBe(true); expect(handler.callCount).toBe(1); @@ -865,8 +857,8 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -874,16 +866,10 @@ describe('RestrictedControllerMessenger', () => { const handler1 = sinon.stub(); const handler2 = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler1, - ); + restrictedMessenger.subscribe('MessageController:message', handler1); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler2, - ); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.subscribe('MessageController:message', handler2); + restrictedMessenger.publish('MessageController:message', 'hello'); expect(handler1.calledWithExactly('hello')).toBe(true); expect(handler1.callCount).toBe(1); @@ -896,24 +882,18 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); + restrictedMessenger.subscribe('MessageController:message', handler); - restrictedControllerMessenger.unsubscribe( - 'MessageController:message', - handler, - ); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.unsubscribe('MessageController:message', handler); + restrictedMessenger.publish('MessageController:message', 'hello'); expect(handler.callCount).toBe(0); }); @@ -923,8 +903,8 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -932,10 +912,7 @@ describe('RestrictedControllerMessenger', () => { const handler = sinon.stub(); expect(() => - restrictedControllerMessenger.unsubscribe( - 'MessageController:message', - handler, - ), + restrictedMessenger.unsubscribe('MessageController:message', handler), ).toThrow(`Subscription not found for event: MessageController:message`); }); @@ -944,8 +921,8 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], @@ -953,16 +930,10 @@ describe('RestrictedControllerMessenger', () => { const handler1 = sinon.stub(); const handler2 = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler1, - ); + restrictedMessenger.subscribe('MessageController:message', handler1); expect(() => - restrictedControllerMessenger.unsubscribe( - 'MessageController:message', - handler2, - ), + restrictedMessenger.unsubscribe('MessageController:message', handler2), ).toThrow(`Subscription not found for event: MessageController:message`); }); @@ -971,23 +942,18 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); + restrictedMessenger.subscribe('MessageController:message', handler); - restrictedControllerMessenger.clearEventSubscriptions( - 'MessageController:message', - ); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.clearEventSubscriptions('MessageController:message'); + restrictedMessenger.publish('MessageController:message', 'hello'); expect(handler.callCount).toBe(0); }); @@ -997,17 +963,15 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); expect(() => - restrictedControllerMessenger.clearEventSubscriptions( - 'MessageController:message', - ), + restrictedMessenger.clearEventSubscriptions('MessageController:message'), ).not.toThrow(); }); @@ -1016,21 +980,21 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'CountController', allowedActions: [], allowedEvents: [], }); let count = 0; - restrictedControllerMessenger.registerActionHandler( + restrictedMessenger.registerActionHandler( 'CountController:count', (increment: number) => { count += increment; }, ); - restrictedControllerMessenger.call('CountController:count', 1); + restrictedMessenger.call('CountController:count', 1); expect(count).toBe(1); }); @@ -1040,14 +1004,13 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger(); - const externalRestrictedControllerMessenger = - controllerMessenger.getRestricted({ - name: 'CountController', - allowedActions: [], - allowedEvents: [], - }); - const restrictedControllerMessenger = controllerMessenger.getRestricted< + const messenger = new Messenger(); + const externalRestrictedMessenger = messenger.getRestricted({ + name: 'CountController', + allowedActions: [], + allowedEvents: [], + }); + const restrictedMessenger = messenger.getRestricted< 'OtherController', CountAction['type'] >({ @@ -1057,13 +1020,13 @@ describe('RestrictedControllerMessenger', () => { }); let count = 0; - externalRestrictedControllerMessenger.registerActionHandler( + externalRestrictedMessenger.registerActionHandler( 'CountController:count', (increment: number) => { count += increment; }, ); - restrictedControllerMessenger.call('CountController:count', 1); + restrictedMessenger.call('CountController:count', 1); expect(count).toBe(1); }); @@ -1073,20 +1036,17 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const restrictedControllerMessenger = controllerMessenger.getRestricted({ + const messenger = new Messenger(); + const restrictedMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: [], }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); + restrictedMessenger.subscribe('MessageController:message', handler); - restrictedControllerMessenger.publish('MessageController:message', 'hello'); + restrictedMessenger.publish('MessageController:message', 'hello'); expect(handler.calledWithExactly('hello')).toBe(true); expect(handler.callCount).toBe(1); @@ -1097,14 +1057,13 @@ describe('RestrictedControllerMessenger', () => { type: 'MessageController:message'; payload: [string]; }; - const controllerMessenger = new ControllerMessenger(); - const externalRestrictedControllerMessenger = - controllerMessenger.getRestricted({ - name: 'MessageController', - allowedActions: [], - allowedEvents: [], - }); - const restrictedControllerMessenger = controllerMessenger.getRestricted< + const messenger = new Messenger(); + const externalRestrictedMessenger = messenger.getRestricted({ + name: 'MessageController', + allowedActions: [], + allowedEvents: [], + }); + const restrictedMessenger = messenger.getRestricted< 'OtherController', never, MessageEvent['type'] @@ -1115,15 +1074,9 @@ describe('RestrictedControllerMessenger', () => { }); const handler = sinon.stub(); - restrictedControllerMessenger.subscribe( - 'MessageController:message', - handler, - ); + restrictedMessenger.subscribe('MessageController:message', handler); - externalRestrictedControllerMessenger.publish( - 'MessageController:message', - 'hello', - ); + externalRestrictedMessenger.publish('MessageController:message', 'hello'); expect(handler.calledWithExactly('hello')).toBe(true); expect(handler.callCount).toBe(1); @@ -1140,24 +1093,21 @@ describe('RestrictedControllerMessenger', () => { type: 'CountController:count'; handler: (increment: number) => void; }; - const controllerMessenger = new ControllerMessenger< - MessageAction | CountAction, - never - >(); + const messenger = new Messenger(); - const messageControllerMessenger = controllerMessenger.getRestricted({ + const messageMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: ['CountController:count'], allowedEvents: [], }); - const countControllerMessenger = controllerMessenger.getRestricted({ + const countMessenger = messenger.getRestricted({ name: 'CountController', allowedActions: [], allowedEvents: [], }); let count = 0; - countControllerMessenger.registerActionHandler( + countMessenger.registerActionHandler( 'CountController:count', (increment: number) => { count += increment; @@ -1165,22 +1115,22 @@ describe('RestrictedControllerMessenger', () => { ); let fullMessage = ''; - messageControllerMessenger.registerActionHandler( + messageMessenger.registerActionHandler( 'MessageController:concat', (message: string) => { fullMessage += message; }, ); - messageControllerMessenger.registerActionHandler( + messageMessenger.registerActionHandler( 'MessageController:reset', (message: string) => { fullMessage = message; }, ); - messageControllerMessenger.call('MessageController:reset', 'hello'); - messageControllerMessenger.call('CountController:count', 1); + messageMessenger.call('MessageController:reset', 'hello'); + messageMessenger.call('CountController:count', 1); expect(fullMessage).toBe('hello'); expect(count).toBe(1); @@ -1191,35 +1141,29 @@ describe('RestrictedControllerMessenger', () => { | { type: 'MessageController:message'; payload: [string] } | { type: 'MessageController:ping'; payload: [] }; type CountEvent = { type: 'CountController:update'; payload: [number] }; - const controllerMessenger = new ControllerMessenger< - never, - MessageEvent | CountEvent - >(); + const messenger = new Messenger(); - const messageControllerMessenger = controllerMessenger.getRestricted({ + const messageMessenger = messenger.getRestricted({ name: 'MessageController', allowedActions: [], allowedEvents: ['CountController:update'], }); - const countControllerMessenger = controllerMessenger.getRestricted({ + const countMessenger = messenger.getRestricted({ name: 'CountController', allowedActions: [], allowedEvents: [], }); let pings = 0; - messageControllerMessenger.subscribe('MessageController:ping', () => { + messageMessenger.subscribe('MessageController:ping', () => { pings += 1; }); let currentCount; - messageControllerMessenger.subscribe( - 'CountController:update', - (newCount: number) => { - currentCount = newCount; - }, - ); - messageControllerMessenger.publish('MessageController:ping'); - countControllerMessenger.publish('CountController:update', 10); + messageMessenger.subscribe('CountController:update', (newCount: number) => { + currentCount = newCount; + }); + messageMessenger.publish('MessageController:ping'); + countMessenger.publish('CountController:update', 10); expect(pings).toBe(1); expect(currentCount).toBe(10); diff --git a/packages/base-controller/src/RestrictedControllerMessenger.ts b/packages/base-controller/src/RestrictedMessenger.ts similarity index 73% rename from packages/base-controller/src/RestrictedControllerMessenger.ts rename to packages/base-controller/src/RestrictedMessenger.ts index 62c8ae0f8e..f9976b2df7 100644 --- a/packages/base-controller/src/RestrictedControllerMessenger.ts +++ b/packages/base-controller/src/RestrictedMessenger.ts @@ -1,7 +1,7 @@ import type { ActionConstraint, ActionHandler, - ControllerMessenger, + Messenger, EventConstraint, ExtractActionParameters, ExtractActionResponse, @@ -11,29 +11,40 @@ import type { NotNamespacedBy, SelectorEventHandler, SelectorFunction, -} from './ControllerMessenger'; +} from './Messenger'; /** - * A universal supertype of all `RestrictedControllerMessenger` instances. - * This type can be assigned to any `RestrictedControllerMessenger` type. + * A universal supertype of all `RestrictedMessenger` instances. This type can be assigned to any + * `RestrictedMessenger` type. * - * @template ControllerName - Name of the controller. Optionally can be used to - * narrow this type to a constraint for the messenger of a specific controller. + * @template Namespace - Name of the module this messenger is for. Optionally can be used to + * narrow this type to a constraint for the messenger of a specific module. + */ +export type RestrictedMessengerConstraint = + RestrictedMessenger< + Namespace, + ActionConstraint, + EventConstraint, + string, + string + >; + +/** + * A universal supertype of all `RestrictedMessenger` instances. This type can be assigned to any + * `RestrictedMessenger` type. + * + * @template Namespace - Name of the module this messenger is for. Optionally can be used to + * narrow this type to a constraint for the messenger of a specific module. + * @deprecated This has been renamed to `RestrictedMessengerConstraint`. */ export type RestrictedControllerMessengerConstraint< - ControllerName extends string = string, -> = RestrictedControllerMessenger< - ControllerName, - ActionConstraint, - EventConstraint, - string, - string ->; + Namespace extends string = string, +> = RestrictedMessengerConstraint; /** - * A restricted controller messenger. + * A restricted messenger. * - * This acts as a wrapper around the controller messenger instance that restricts access to actions + * This acts as a wrapper around the messenger instance that restricts access to actions * and events. * * @template Namespace - The namespace for this messenger. Typically this is the name of the controller or @@ -46,55 +57,64 @@ export type RestrictedControllerMessengerConstraint< * @template AllowedEvent - A type union of the 'type' string for any allowed events. * This must not include internal events that are in the messenger's namespace. */ -export class RestrictedControllerMessenger< +export class RestrictedMessenger< Namespace extends string, Action extends ActionConstraint, Event extends EventConstraint, AllowedAction extends string, AllowedEvent extends string, > { - readonly #controllerMessenger: ControllerMessenger< - ActionConstraint, - EventConstraint - >; + readonly #messenger: Messenger; - readonly #controllerName: Namespace; + readonly #namespace: Namespace; readonly #allowedActions: NotNamespacedBy[]; readonly #allowedEvents: NotNamespacedBy[]; /** - * Constructs a restricted controller messenger + * Constructs a restricted messenger * * The provided allowlists grant the ability to call the listed actions and subscribe to the * listed events. The "name" provided grants ownership of any actions and events under that * namespace. Ownership allows registering actions and publishing events, as well as * unregistering actions and clearing event subscriptions. * - * @param options - The controller options. - * @param options.controllerMessenger - The controller messenger instance that is being wrapped. + * @param options - Options. + * @param options.controllerMessenger - The messenger instance that is being wrapped. (deprecated) + * @param options.messenger - The messenger instance that is being wrapped. * @param options.name - The name of the thing this messenger will be handed to (e.g. the * controller name). This grants "ownership" of actions and events under this namespace to the - * restricted controller messenger returned. - * @param options.allowedActions - The list of actions that this restricted controller messenger - * should be alowed to call. - * @param options.allowedEvents - The list of events that this restricted controller messenger - * should be allowed to subscribe to. + * restricted messenger returned. + * @param options.allowedActions - The list of actions that this restricted messenger should be + * allowed to call. + * @param options.allowedEvents - The list of events that this restricted messenger should be + * allowed to subscribe to. */ constructor({ controllerMessenger, + messenger, name, allowedActions, allowedEvents, }: { - controllerMessenger: ControllerMessenger; + controllerMessenger?: Messenger; + messenger?: Messenger; name: Namespace; allowedActions: NotNamespacedBy[]; allowedEvents: NotNamespacedBy[]; }) { - this.#controllerMessenger = controllerMessenger; - this.#controllerName = name; + if (messenger && controllerMessenger) { + throw new Error( + `Both messenger properties provided. Provide message using only 'messenger' option, 'controllerMessenger' is deprecated`, + ); + } else if (!messenger && !controllerMessenger) { + throw new Error('Messenger not provided'); + } + // The above condition guarantees that one of these options is defined. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.#messenger = (messenger ?? controllerMessenger)!; + this.#namespace = name; this.#allowedActions = allowedActions; this.#allowedEvents = allowedEvents; } @@ -119,11 +139,11 @@ export class RestrictedControllerMessenger< if (!this.#isInCurrentNamespace(action)) { throw new Error( `Only allowed registering action handlers prefixed by '${ - this.#controllerName + this.#namespace }:'`, ); } - this.#controllerMessenger.registerActionHandler(action, handler); + this.#messenger.registerActionHandler(action, handler); } /** @@ -144,11 +164,11 @@ export class RestrictedControllerMessenger< if (!this.#isInCurrentNamespace(action)) { throw new Error( `Only allowed unregistering action handlers prefixed by '${ - this.#controllerName + this.#namespace }:'`, ); } - this.#controllerMessenger.unregisterActionHandler(action); + this.#messenger.unregisterActionHandler(action); } /** @@ -177,10 +197,7 @@ export class RestrictedControllerMessenger< if (!this.#isAllowedAction(actionType)) { throw new Error(`Action missing from allow list: ${actionType}`); } - const response = this.#controllerMessenger.call( - actionType, - ...params, - ); + const response = this.#messenger.call(actionType, ...params); return response; } @@ -210,10 +227,10 @@ export class RestrictedControllerMessenger< /* istanbul ignore if */ // Branch unreachable with valid types if (!this.#isInCurrentNamespace(eventType)) { throw new Error( - `Only allowed publishing events prefixed by '${this.#controllerName}:'`, + `Only allowed publishing events prefixed by '${this.#namespace}:'`, ); } - this.#controllerMessenger.registerInitialEventPayload({ + this.#messenger.registerInitialEventPayload({ eventType, getPayload, }); @@ -239,10 +256,10 @@ export class RestrictedControllerMessenger< /* istanbul ignore if */ // Branch unreachable with valid types if (!this.#isInCurrentNamespace(event)) { throw new Error( - `Only allowed publishing events prefixed by '${this.#controllerName}:'`, + `Only allowed publishing events prefixed by '${this.#namespace}:'`, ); } - this.#controllerMessenger.publish(event, ...payload); + this.#messenger.publish(event, ...payload); } /** @@ -255,7 +272,7 @@ export class RestrictedControllerMessenger< * @param eventType - The event type. This is a unique identifier for this event. * @param handler - The event handler. The type of the parameters for this event handler must * match the type of the payload for this event type. - * @throws Will throw if the given event is not an allowed event for this controller messenger. + * @throws Will throw if the given event is not an allowed event for this messenger. * @template EventType - A type union of Event type strings. */ subscribe< @@ -280,7 +297,7 @@ export class RestrictedControllerMessenger< * @param selector - The selector function used to select relevant data from * the event payload. The type of the parameters for this selector must match * the type of the payload for this event type. - * @throws Will throw if the given event is not an allowed event for this controller messenger. + * @throws Will throw if the given event is not an allowed event for this messenger. * @template EventType - A type union of Event type strings. * @template SelectorReturnValue - The selector return value. */ @@ -310,9 +327,9 @@ export class RestrictedControllerMessenger< } if (selector) { - return this.#controllerMessenger.subscribe(event, handler, selector); + return this.#messenger.subscribe(event, handler, selector); } - return this.#controllerMessenger.subscribe(event, handler); + return this.#messenger.subscribe(event, handler); } /** @@ -324,7 +341,7 @@ export class RestrictedControllerMessenger< * * @param event - The event type. This is a unique identifier for this event. * @param handler - The event handler to unregister. - * @throws Will throw if the given event is not an allowed event for this controller messenger. + * @throws Will throw if the given event is not an allowed event for this messenger. * @template EventType - A type union of allowed Event type strings. */ unsubscribe< @@ -335,7 +352,7 @@ export class RestrictedControllerMessenger< if (!this.#isAllowedEvent(event)) { throw new Error(`Event missing from allow list: ${event}`); } - this.#controllerMessenger.unsubscribe(event, handler); + this.#messenger.unsubscribe(event, handler); } /** @@ -354,10 +371,10 @@ export class RestrictedControllerMessenger< >(event: EventType) { if (!this.#isInCurrentNamespace(event)) { throw new Error( - `Only allowed clearing events prefixed by '${this.#controllerName}:'`, + `Only allowed clearing events prefixed by '${this.#namespace}:'`, ); } - this.#controllerMessenger.clearEventSubscriptions(event); + this.#messenger.clearEventSubscriptions(event); } /** @@ -409,6 +426,35 @@ export class RestrictedControllerMessenger< * @returns Whether the name is within the current namespace */ #isInCurrentNamespace(name: string): name is NamespacedName { - return name.startsWith(`${this.#controllerName}:`); + return name.startsWith(`${this.#namespace}:`); } } + +/** + * Constructs a restricted messenger + * + * The provided allowlists grant the ability to call the listed actions and subscribe to the + * listed events. The "name" provided grants ownership of any actions and events under that + * namespace. Ownership allows registering actions and publishing events, as well as + * unregistering actions and clearing event subscriptions. + * + * @param options - Options. + * @param options.controllerMessenger - The messenger instance that is being wrapped. (deprecated) + * @param options.messenger - The messenger instance that is being wrapped. + * @param options.name - The name of the thing this messenger will be handed to (e.g. the + * controller name). This grants "ownership" of actions and events under this namespace to the + * restricted messenger returned. + * @param options.allowedActions - The list of actions that this restricted messenger should be + * allowed to call. + * @param options.allowedEvents - The list of events that this restricted messenger should be + * allowed to subscribe to. + * @deprecated This has been renamed to `RestrictedMessenger`. + */ +export const RestrictedControllerMessenger = RestrictedMessenger; +export type RestrictedControllerMessenger< + Namespace extends string, + Action extends ActionConstraint, + Event extends EventConstraint, + AllowedAction extends string, + AllowedEvent extends string, +> = RestrictedMessenger; diff --git a/packages/base-controller/src/index.ts b/packages/base-controller/src/index.ts index a4eab5b572..af19ddfc50 100644 --- a/packages/base-controller/src/index.ts +++ b/packages/base-controller/src/index.ts @@ -41,7 +41,13 @@ export type { NamespacedBy, NotNamespacedBy, NamespacedName, -} from './ControllerMessenger'; -export { ControllerMessenger } from './ControllerMessenger'; -export type { RestrictedControllerMessengerConstraint } from './RestrictedControllerMessenger'; -export { RestrictedControllerMessenger } from './RestrictedControllerMessenger'; +} from './Messenger'; +export { ControllerMessenger, Messenger } from './Messenger'; +export type { + RestrictedControllerMessengerConstraint, + RestrictedMessengerConstraint, +} from './RestrictedMessenger'; +export { + RestrictedControllerMessenger, + RestrictedMessenger, +} from './RestrictedMessenger'; From 9c00587b7fc0669c8b26e892a3c6d5f89b0e01e9 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 10 Dec 2024 18:16:47 -0330 Subject: [PATCH 2/2] Fix and simplify aliases --- packages/base-controller/src/Messenger.ts | 17 +---------- .../src/RestrictedMessenger.ts | 29 +------------------ 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/packages/base-controller/src/Messenger.ts b/packages/base-controller/src/Messenger.ts index fbc225efb9..4d10201913 100644 --- a/packages/base-controller/src/Messenger.ts +++ b/packages/base-controller/src/Messenger.ts @@ -459,19 +459,4 @@ export class Messenger< } } -/** - * A message broker for "actions" and "events". - * - * The messenger allows registering functions as 'actions' that can be called elsewhere, - * and it allows publishing and subscribing to events. Both actions and events are identified by - * unique strings. - * - * @template Action - A type union of all Action types. - * @template Event - A type union of all Event types. - * @deprecated This has been renamed to `Messenger`. - */ -export const ControllerMessenger = Messenger; -export type ControllerMessenger< - Action extends ActionConstraint, - Event extends EventConstraint, -> = Messenger; +export { Messenger as ControllerMessenger }; diff --git a/packages/base-controller/src/RestrictedMessenger.ts b/packages/base-controller/src/RestrictedMessenger.ts index f9976b2df7..c1cd62b6ad 100644 --- a/packages/base-controller/src/RestrictedMessenger.ts +++ b/packages/base-controller/src/RestrictedMessenger.ts @@ -430,31 +430,4 @@ export class RestrictedMessenger< } } -/** - * Constructs a restricted messenger - * - * The provided allowlists grant the ability to call the listed actions and subscribe to the - * listed events. The "name" provided grants ownership of any actions and events under that - * namespace. Ownership allows registering actions and publishing events, as well as - * unregistering actions and clearing event subscriptions. - * - * @param options - Options. - * @param options.controllerMessenger - The messenger instance that is being wrapped. (deprecated) - * @param options.messenger - The messenger instance that is being wrapped. - * @param options.name - The name of the thing this messenger will be handed to (e.g. the - * controller name). This grants "ownership" of actions and events under this namespace to the - * restricted messenger returned. - * @param options.allowedActions - The list of actions that this restricted messenger should be - * allowed to call. - * @param options.allowedEvents - The list of events that this restricted messenger should be - * allowed to subscribe to. - * @deprecated This has been renamed to `RestrictedMessenger`. - */ -export const RestrictedControllerMessenger = RestrictedMessenger; -export type RestrictedControllerMessenger< - Namespace extends string, - Action extends ActionConstraint, - Event extends EventConstraint, - AllowedAction extends string, - AllowedEvent extends string, -> = RestrictedMessenger; +export { RestrictedMessenger as RestrictedControllerMessenger };