-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathevent.ts
More file actions
58 lines (47 loc) · 1.46 KB
/
event.ts
File metadata and controls
58 lines (47 loc) · 1.46 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
import type { EventData, EventType } from './types.js';
const namespace = 'nmr-wrapper';
function trigger<T extends EventType>(type: T, data: EventData<T>) {
window.parent.postMessage({ type: `${namespace}:${type}`, data }, '*');
}
function on<T extends EventType>(
type: T,
dataListener: (data: EventData<T>) => void,
options: {
eventOptions?: boolean | AddEventListenerOptions;
allowedOrigins?: string[];
} = {},
) {
const { eventOptions, allowedOrigins = [] } = options;
const allowedHostnames = new Set(
allowedOrigins.map(getHostName).filter(Boolean),
);
function listener(event: MessageEvent) {
const {
origin,
data: { type: targetType, data },
} = event;
const url = new URL(origin);
const skipOriginCheck =
allowedOrigins.length === 0 || allowedOrigins.includes('*');
if (!skipOriginCheck && !allowedHostnames.has(getHostName(url.origin))) {
throw new Error(`Invalid Origin ${origin}`);
}
if (`${namespace}:${type}` === targetType) {
dataListener?.(data);
}
}
window.addEventListener(`message`, listener, eventOptions);
return () => window.removeEventListener(`message`, listener);
}
function getHostName(origin: string) {
try {
const { hostname } = new URL(origin);
return hostname;
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
// return null If the URL is invalid
return null;
}
}
export default { trigger, on };