@metamask/base-controller
Version:
Provides scaffolding for controllers as well a communication system for all controllers
231 lines • 12.7 kB
text/typescript
import { RestrictedMessenger } from "./RestrictedMessenger.cjs";
export type ActionHandler<Action extends ActionConstraint, ActionType = Action['type']> = (...args: ExtractActionParameters<Action, ActionType>) => ExtractActionResponse<Action, ActionType>;
export type ExtractActionParameters<Action extends ActionConstraint, ActionType = Action['type']> = Action extends {
type: ActionType;
handler: (...args: infer HandlerArgs) => unknown;
} ? HandlerArgs : never;
export type ExtractActionResponse<Action extends ActionConstraint, ActionType = Action['type']> = Action extends {
type: ActionType;
handler: (...args: infer _) => infer HandlerReturnValue;
} ? HandlerReturnValue : never;
export type ExtractEventHandler<Event extends EventConstraint, EventType = Event['type']> = Event extends {
type: EventType;
payload: infer Payload;
} ? Payload extends unknown[] ? (...payload: Payload) => void : never : never;
export type ExtractEventPayload<Event extends EventConstraint, EventType = Event['type']> = Event extends {
type: EventType;
payload: infer Payload;
} ? Payload extends unknown[] ? Payload : never : never;
export type GenericEventHandler = (...args: unknown[]) => void;
export type SelectorFunction<Event extends EventConstraint, EventType extends Event['type'], ReturnValue = unknown> = (...args: ExtractEventPayload<Event, EventType>) => ReturnValue;
export type SelectorEventHandler<SelectorReturnValue = unknown> = (newValue: SelectorReturnValue, previousValue: SelectorReturnValue | undefined) => void;
export type ActionConstraint = {
type: string;
handler: ((...args: never) => unknown) | ((...args: never[]) => unknown);
};
export type EventConstraint = {
type: string;
payload: unknown[];
};
/**
* A namespaced string
*
* This type verifies that the string Name is prefixed by the string Name followed by a colon.
*
* @template Namespace - The namespace we're checking for.
* @template Name - The full string, including the namespace.
*/
export type NamespacedBy<Namespace extends string, Name extends string> = Name extends `${Namespace}:${string}` ? Name : never;
export type NotNamespacedBy<Namespace extends string, Name extends string> = Name extends `${Namespace}:${string}` ? never : Name;
export type NamespacedName<Namespace extends string = string> = `${Namespace}:${string}`;
type NarrowToNamespace<Name, Namespace extends string> = Name extends {
type: `${Namespace}:${string}`;
} ? Name : never;
type NarrowToAllowed<Name, Allowed extends string> = Name extends {
type: Allowed;
} ? Name : never;
/**
* 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.
*/
export declare class Messenger<Action extends ActionConstraint, Event extends EventConstraint> {
#private;
/**
* Register an action handler.
*
* This will make the registered function available to call via the `call` method.
*
* @param actionType - The action type. This is a unique identifier for this action.
* @param handler - The action handler. This function gets called when the `call` method is
* invoked with the given action type.
* @throws Will throw when a handler has been registered for this action type already.
* @template ActionType - A type union of Action type strings.
*/
registerActionHandler<ActionType extends Action['type']>(actionType: ActionType, handler: ActionHandler<Action, ActionType>): void;
/**
* Registers action handlers for a list of methods on a messenger client
*
* @param messengerClient - The object that is expected to make use of the messenger.
* @param methodNames - The names of the methods on the messenger client to register as action
* handlers.
* @template MessengerClient - The type expected to make use of the messenger.
* @template MethodNames - The type union of method names to register as action handlers.
*/
registerMethodActionHandlers<MessengerClient extends {
name: string;
}, MethodNames extends keyof MessengerClient & string>(messengerClient: MessengerClient, methodNames: readonly MethodNames[]): void;
/**
* Unregister an action handler.
*
* This will prevent this action from being called.
*
* @param actionType - The action type. This is a unique identifier for this action.
* @template ActionType - A type union of Action type strings.
*/
unregisterActionHandler<ActionType extends Action['type']>(actionType: ActionType): void;
/**
* Unregister all action handlers.
*
* This prevents all actions from being called.
*/
clearActions(): void;
/**
* Call an action.
*
* This function will call the action handler corresponding to the given action type, passing
* along any parameters given.
*
* @param actionType - The action type. This is a unique identifier for this action.
* @param params - The action parameters. These must match the type of the parameters of the
* registered action handler.
* @throws Will throw when no handler has been registered for the given type.
* @template ActionType - A type union of Action type strings.
* @returns The action return value.
*/
call<ActionType extends Action['type']>(actionType: ActionType, ...params: ExtractActionParameters<Action, ActionType>): ExtractActionResponse<Action, ActionType>;
/**
* Register a function for getting the initial payload for an event.
*
* This is used for events that represent a state change, where the payload is the state.
* Registering a function for getting the payload allows event selectors to have a point of
* comparison the first time state changes.
*
* @param args - The arguments to this function
* @param args.eventType - The event type to register a payload for.
* @param args.getPayload - A function for retrieving the event payload.
* @template EventType - A type union of Event type strings.
*/
registerInitialEventPayload<EventType extends Event['type']>({ eventType, getPayload, }: {
eventType: EventType;
getPayload: () => ExtractEventPayload<Event, EventType>;
}): void;
/**
* Publish an event.
*
* Publishes the given payload to all subscribers of the given event type.
*
* Note that this method should never throw directly. Any errors from
* subscribers are captured and re-thrown in a timeout handler.
*
* @param eventType - The event type. This is a unique identifier for this event.
* @param payload - The event payload. The type of the parameters for each event handler must
* match the type of this payload.
* @template EventType - A type union of Event type strings.
*/
publish<EventType extends Event['type']>(eventType: EventType, ...payload: ExtractEventPayload<Event, EventType>): void;
/**
* Subscribe to an event.
*
* Registers the given function as an event handler for the given event type.
*
* @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.
* @template EventType - A type union of Event type strings.
*/
subscribe<EventType extends Event['type']>(eventType: EventType, handler: ExtractEventHandler<Event, EventType>): void;
/**
* Subscribe to an event, with a selector.
*
* Registers the given handler function as an event handler for the given
* event type. When an event is published, its payload is first passed to the
* selector. The event handler is only called if the selector's return value
* differs from its last known return value.
*
* @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 return type of the selector.
* @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.
* @template EventType - A type union of Event type strings.
* @template SelectorReturnValue - The selector return value.
*/
subscribe<EventType extends Event['type'], SelectorReturnValue>(eventType: EventType, handler: SelectorEventHandler<SelectorReturnValue>, selector: SelectorFunction<Event, EventType, SelectorReturnValue>): void;
/**
* Unsubscribe from an event.
*
* Unregisters the given function as an event handler for the given event.
*
* @param eventType - The event type. This is a unique identifier for this event.
* @param handler - The event handler to unregister.
* @throws Will throw when the given event handler is not registered for this event.
* @template EventType - A type union of Event type strings.
* @template SelectorReturnValue - The selector return value.
*/
unsubscribe<EventType extends Event['type'], SelectorReturnValue = unknown>(eventType: EventType, handler: ExtractEventHandler<Event, EventType> | SelectorEventHandler<SelectorReturnValue>): void;
/**
* Clear subscriptions for a specific event.
*
* This will remove all subscribed handlers for this event.
*
* @param eventType - The event type. This is a unique identifier for this event.
* @template EventType - A type union of Event type strings.
*/
clearEventSubscriptions<EventType extends Event['type']>(eventType: EventType): void;
/**
* Clear all subscriptions.
*
* This will remove all subscribed handlers for all events.
*/
clearSubscriptions(): void;
/**
* Get a restricted messenger
*
* 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 - 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 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 messenger.
*/
getRestricted<Namespace extends string, AllowedAction extends NotNamespacedBy<Namespace, Action['type']> = never, AllowedEvent extends NotNamespacedBy<Namespace, Event['type']> = never>({ name, allowedActions, allowedEvents, }: {
name: Namespace;
allowedActions: NotNamespacedBy<Namespace, Extract<Action['type'], AllowedAction>>[];
allowedEvents: NotNamespacedBy<Namespace, Extract<Event['type'], AllowedEvent>>[];
}): RestrictedMessenger<Namespace, NarrowToNamespace<Action, Namespace> | NarrowToAllowed<Action, AllowedAction>, NarrowToNamespace<Event, Namespace> | NarrowToAllowed<Event, AllowedEvent>, AllowedAction, AllowedEvent>;
}
export {};
//# sourceMappingURL=Messenger.d.cts.map