-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathvscode-bridge.utils.ts
More file actions
63 lines (50 loc) · 1.54 KB
/
Copy pathvscode-bridge.utils.ts
File metadata and controls
63 lines (50 loc) · 1.54 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
import type {
AppMessage,
HostMessage,
PayloadOf,
} from '@lemoncode/quickmock-bridge-protocol';
import { isVSCodeEnv } from './env.utils';
type HandlerFor<T extends HostMessage['type']> = (
payload: PayloadOf<HostMessage, T>
) => void;
type AnyHandler = (payload: unknown) => void;
const handlers = new Map<string, Set<AnyHandler>>();
const resolveParentOrigin = (): string => {
if (!document.referrer) return '*';
try {
return new URL(document.referrer).origin;
} catch {
return '*';
}
};
const parentOrigin = resolveParentOrigin();
export const sendToExtension = (msg: AppMessage): void => {
if (!isVSCodeEnv()) return;
window.parent.postMessage(msg, parentOrigin);
};
export const onMessage = <T extends HostMessage['type']>(
type: T,
handler: HandlerFor<T>
): (() => void) => {
if (!isVSCodeEnv()) return () => {};
const existing = handlers.get(type) ?? new Set<AnyHandler>();
existing.add(handler as AnyHandler);
handlers.set(type, existing);
return () => {
const set = handlers.get(type);
if (!set) return;
set.delete(handler as AnyHandler);
if (set.size === 0) handlers.delete(type);
};
};
if (isVSCodeEnv()) {
window.addEventListener('message', (event: MessageEvent) => {
if (event.source !== window.parent) return;
const msg = event.data as Partial<HostMessage> | undefined;
if (!msg?.type) return;
const set = handlers.get(msg.type);
if (!set) return;
const payload = (msg as { payload?: unknown }).payload;
for (const handler of set) handler(payload);
});
}