-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
75 lines (65 loc) · 1.92 KB
/
index.js
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
'use strict'
const {join: pathJoin} = require('path')
const {readFileSync} = require('fs')
const {createServer} = require('http')
const accepts = require('accepts')
const finalhandler = require('finalhandler')
const {promisify} = require('util')
const DIR = pathJoin(__dirname, 'lib')
const INJECT = readFileSync(pathJoin(__dirname, 'inject.js'), {encoding: 'utf8'})
const RAW_INDEX = readFileSync(pathJoin(DIR, 'index.html'), {encoding: 'utf8'})
const INDEX = RAW_INDEX.replace('</body>', `<script>${INJECT}</script></body>`)
const visualizeExplainFile = async (explainResult, query, opt = {}) => {
const {
once,
name,
} = {
once: false,
name: 'new-plan',
...opt,
}
const app = createServer((req, res) => {
if (once) res.setHeader('connection', 'close')
const path = new URL(req.url, 'http://example.org').pathname
if (path === '/') {
res.setHeader('content-type', 'text/html')
res.end(INDEX)
} else if (path === '/data' && accepts(req).type(['json']) === 'json') {
if (once) {
res.once('finish', () => {
// Ugly but effective way to make sure all resources have
// been fetched by the client.
setTimeout(() => {
stop().catch(console.error)
}, 1000)
})
}
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({name, explainResult, query}))
} else {
res.writeHead(404)
res.end()
}
})
const port = 10000 + (Math.random() * 10000 | 0) // todo: pick port properly
const listen = promisify(app.listen.bind(app))
await listen({
host: 'localhost',
port,
})
const stop = async () => {
await promisify(app.close.bind(app))()
}
const url = new URL('http://example.org')
{
const {family, address, port} = app.address()
// work around https://github.com/nodejs/node/issues/49650
url.hostname = family === 'IPv6' ? `[${address}]` : address
url.port = port
}
return {
stop,
url: url.href,
}
}
module.exports = visualizeExplainFile