-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrowser.js
More file actions
139 lines (123 loc) · 2.96 KB
/
browser.js
File metadata and controls
139 lines (123 loc) · 2.96 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import HClient from './src/HClient'
import msgpack from '@msgpack/msgpack'
import Queue from 'async-await-queue'
import { bigIntCodec } from './src/ExtensionCodecs'
const extensionCodec = new msgpack.ExtensionCodec()
bigIntCodec(extensionCodec, msgpack.encode, msgpack.decode)
const queue = new Queue(3, 100)
/**
* @module browser
*/
/**
* Hoctail query client public API
*
* Browser-specific mixin
* @extends HClient
*/
class Client extends HClient {
/**
* Create websocket
* Auth is managed by browser (cookies)
* @protected
*/
createSocket () {
this.ws = new WebSocket(this.getEndpoint())
}
get closed () {
return this.ws == null || this.ws.readyState === WebSocket.CLOSED
}
decode (event) {
if (!event.hasOwnProperty('decoded')) {
event.decoded = Client.msgpack.decode(event.data)
}
return event.decoded
}
encode (obj) {
return Client.msgpack.encode(obj)
}
/**
* Heartbeat is managed by browser, noop here
* @protected
*/
heartbeat () {
}
/**
* Get app name from browser url
* @type {string}
*/
get app () {
if (this._app != null || this.schema != null) {
return this._app
}
return this._app = Client.parseApp()
}
set app (value) {
throw new Error('Cannot set app name in browser')
}
/**
* Set up live reload for browser apps
*/
liveReload () {
(async () => {
try {
await this.call('http_server.dev_subscribe')
this.ws.removeEventListener('message', this._cmdHandler)
this.ws.addEventListener('message', this._cmdHandler)
} catch (e) {
console.log(e.message)
}
})()
}
/**
* Callback that will reload the app on 'refresh' command
* @param {MessageEvent} event
* @private
*/
_cmdHandler (event) {
const message = this.decode(event)
if (message.type === 'cmd') {
const msg = message.msg
switch (msg.cmd) {
case 'refresh':
window.location.reload()
break
default:
console.log(`Unknown command received: ${msg.cmd}`)
}
}
}
async _slotGet (qid, priority) {
return queue.wait(qid, priority)
}
_slotFree (qid) {
queue.end(qid)
}
async _flushQueue () {
return queue.flush()
}
}
/**
* Parse full app path from window.location property
*
* @return {string} app path in 'ownerName/appName' format
* @throws {Error} if cannot parse {@link window.location} properly
*/
Client.parseApp = () => {
const path = window.location.pathname
if (path) {
const parts = path.split('/', 3)
if (parts[1] && parts[2]) {
return `${decodeURIComponent(parts[1])}/${decodeURIComponent(parts[2])}`
}
}
throw new Error(`App name cannot be derived from: ${window.location.pathname}`)
}
Client.msgpack = {
encode: (obj) => {
return msgpack.encode(obj, { extensionCodec })
},
decode: (data) => {
return msgpack.decode(new Uint8Array(data), { extensionCodec })
},
}
export default Client