forked from cerebral/overmind
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBackendConnector.ts
More file actions
121 lines (110 loc) · 2.87 KB
/
BackendConnector.ts
File metadata and controls
121 lines (110 loc) · 2.87 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
109
110
111
112
113
114
115
116
117
118
119
120
121
import { AppMessage, AppMessageType } from './overmind/types'
type Message = {
appName: string
messages: AppMessage<any>[]
}
type MessageCallback = (message: Message) => void
class WebsocketConnector {
private nextEvaluationId = 0
private callbacks: {
[event: string]: Function[]
} = {}
private socket:WebSocket;
private messagesBeforeConnected: Array<[string, any, any]> = []
private isOpen = false
public open(port:string) // TODO: return Promise so we can wait for it
{
if (this.socket)
{
throw new Error("TODO: Socked already open, what now?");
}
this.socket = new WebSocket(`ws://localhost:${port}?devtools=1`)
this.socket.onmessage = (message) => {
const parsedMessage = JSON.parse(message.data)
if (this.callbacks[parsedMessage.type]) {
this.callbacks[parsedMessage.type].forEach((cb) =>
cb(parsedMessage.data)
)
}
}
this.socket.onopen = () => {
this.isOpen = true
this.messagesBeforeConnected.forEach((message) => {
this.send(...message)
})
this.messagesBeforeConnected.length = 0
}
}
on(event: string, cb: Function) {
if (!this.callbacks[event]) {
this.callbacks[event] = []
}
this.callbacks[event].push(cb)
}
off(event, cb) {
if (this.callbacks[event]) {
this.callbacks[event].splice(this.callbacks[event].indexOf(cb), 1)
}
}
send(event: string, data?: any, onEvaluated?: Function) {
if (!this.isOpen) {
this.messagesBeforeConnected.push([event, data, onEvaluated])
return
}
const nextEvaluationId = this.nextEvaluationId++
this.socket.send(
JSON.stringify({
type: event,
data,
evaluate: onEvaluated ? nextEvaluationId : undefined,
})
)
if (onEvaluated) {
const cb = (data) => {
if (data.id === nextEvaluationId) {
this.off('evaluated', cb)
onEvaluated(data.error ? data.error : null, data.data)
}
}
this.on('evaluated', cb)
}
}
}
export class BackendConnector extends WebsocketConnector {
port: string
messageCallback: MessageCallback
constructor() {
super()
this.on('port:exists', this.onPortExists)
}
connect(port: string) {
this.send('connect', port)
}
onMessage = (onMessage: MessageCallback) => {
this.messageCallback = onMessage
this.on('message', (message) => onMessage(message))
}
onPortExists = (_) => {
this.messageCallback({
appName: null,
messages: [
{
appName: '',
type: AppMessageType.PORT_EXISTS,
data: null,
},
],
})
}
sendMessage(appName: string, eventName: string, payload: object = null) {
this.send('message', {
appName,
type: eventName,
data: payload,
})
}
relaunch() {
this.send('relaunch')
}
}
export default BackendConnector