-
-
Notifications
You must be signed in to change notification settings - Fork 278
Expand file tree
/
Copy pathcreateRestrictedMethodMessenger.ts
More file actions
108 lines (101 loc) · 3.14 KB
/
createRestrictedMethodMessenger.ts
File metadata and controls
108 lines (101 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import type {
ActionConstraint,
EventConstraint,
MessengerActions,
} from '@metamask/messenger';
import { Messenger } from '@metamask/messenger';
/**
* The subset of `RootMessenger`'s actions selected by `DelegatedActions`.
*/
type SelectedActions<
RootMessenger extends Messenger<string, ActionConstraint, EventConstraint>,
DelegatedActions extends readonly MessengerActions<RootMessenger>['type'][],
> = Extract<
MessengerActions<RootMessenger>,
{ type: DelegatedActions[number] }
>;
/**
* Create a child messenger scoped to a restricted-method permission
* specification, delegating only the spec's declared actions from the root
* messenger. This produces a minimally-scoped messenger whose action surface
* matches exactly what the spec has declared it needs.
*
* Returns `undefined` when `actionNames` is omitted — there is nothing to
* scope, and the builder can be invoked without a messenger.
*
* @param args - The arguments.
* @param args.rootMessenger - The root messenger to delegate actions from.
* @param args.namespace - The namespace for the scoped child messenger,
* typically the spec's `targetName`.
* @param args.actionNames - The action types the specification requires,
* typically the spec's declared `actionNames`. Must be a non-empty tuple of
* action types that exist on the root messenger.
* @returns A scoped child messenger with the requested actions delegated, or
* `undefined` if no actions were requested.
*/
export function createRestrictedMethodMessenger<
Namespace extends string,
RootMessenger extends Messenger<string, ActionConstraint, EventConstraint>,
DelegatedActions extends readonly [
MessengerActions<RootMessenger>['type'],
...MessengerActions<RootMessenger>['type'][],
],
>(args: {
rootMessenger: RootMessenger;
namespace: Namespace;
actionNames: DelegatedActions;
}): Messenger<
Namespace,
SelectedActions<RootMessenger, DelegatedActions>,
never,
RootMessenger
>;
export function createRestrictedMethodMessenger<
Namespace extends string,
RootMessenger extends Messenger<string, ActionConstraint, EventConstraint>,
>(args: {
rootMessenger: RootMessenger;
namespace: Namespace;
actionNames?: undefined;
}): undefined;
export function createRestrictedMethodMessenger<
Namespace extends string,
RootMessenger extends Messenger<string, ActionConstraint, EventConstraint>,
DelegatedActions extends [
MessengerActions<RootMessenger>['type'],
...MessengerActions<RootMessenger>['type'][],
],
>({
rootMessenger,
namespace,
actionNames,
}: {
rootMessenger: RootMessenger;
namespace: Namespace;
actionNames?: DelegatedActions;
}):
| Messenger<
Namespace,
SelectedActions<RootMessenger, DelegatedActions>,
never,
RootMessenger
>
| undefined {
if (!actionNames?.length) {
return undefined;
}
const restrictedMethodMessenger = new Messenger<
Namespace,
SelectedActions<RootMessenger, DelegatedActions>,
never,
RootMessenger
>({
namespace,
parent: rootMessenger,
});
rootMessenger.delegate({
actions: actionNames,
messenger: restrictedMethodMessenger,
});
return restrictedMethodMessenger;
}