1 | import fs from 'fs'; |
||
2 | import process from 'process'; |
||
3 | import path from 'path'; |
||
4 | import http from 'http'; |
||
5 | import opn from 'opn'; |
||
6 | import watch from 'node-watch'; |
||
7 | import { listen } from 'socket.io'; |
||
8 | import Promise, { promisify, props } from 'bluebird'; |
||
9 | import { |
||
10 | has, |
||
11 | join, |
||
12 | lensProp, |
||
13 | map, |
||
14 | mergeAll, |
||
15 | over, |
||
16 | replace, |
||
17 | when |
||
18 | } from 'ramda'; |
||
19 | import { Converter } from 'showdown'; |
||
20 | import { executeWithParams, readFile } from './run'; |
||
21 | import { emitError, emitInfo, emitSuccess } from './input'; |
||
22 | |||
23 | const readDirectory = promisify(fs.readdir); |
||
24 | |||
25 | /** |
||
26 | * Emits the Rung emoji to the live server ;) |
||
27 | * |
||
28 | * @return {Promise} |
||
29 | */ |
||
30 | function emitRungEmoji() { |
||
31 | return [ |
||
32 | '', |
||
33 | ' ___ _ _______', |
||
34 | ' / _ \\__ __/ |/ / ___/', |
||
35 | ' / , _/ // / / (_ /', |
||
36 | '/_/|_|\\_,_/_/|_/\\___/', |
||
37 | '' |
||
38 | ] | join('\n') | emitInfo; |
||
39 | } |
||
40 | |||
41 | /** |
||
42 | * Returns an object with resource path and buffer |
||
43 | * |
||
44 | * @return {Promise} |
||
45 | */ |
||
46 | const getResources = () => { |
||
47 | const resources = path.join(__dirname, '../resources/live'); |
||
48 | return readDirectory(resources) |
||
49 | .map(filename => props({ |
||
50 | [`/${filename}`]: readFile(path.join(resources, filename)) |
||
51 | })) |
||
52 | .then(mergeAll); |
||
53 | }; |
||
54 | |||
55 | /** |
||
56 | * Compiles the content of the cards to be compatible with HTML |
||
57 | * |
||
58 | * @param {Object} alerts |
||
59 | * @return {Object[]} |
||
60 | */ |
||
61 | const compileMarkdown = alerts => { |
||
62 | const converter = new Converter(); |
||
63 | return alerts |
||
64 | | map(when(has('comment'), |
||
65 | over(lensProp('comment'), replace(/^[ \t]+/gm, '') & converter.makeHtml))); |
||
66 | }; |
||
67 | |||
68 | /** |
||
69 | * Watches folder for file changes, hot recompiling everything and notifying |
||
70 | * the clients |
||
71 | * |
||
72 | * @param {SocketIO} io |
||
73 | * @param {Object} params |
||
74 | * @return {Object} |
||
75 | */ |
||
76 | function watchChanges(io, params) { |
||
77 | const folder = process.cwd(); |
||
78 | return watch(folder, { recursive: true }, () => { |
||
79 | emitInfo('changes detected. Recompiling...'); |
||
80 | io.sockets.emit('load'); |
||
81 | const start = new Date().getTime(); |
||
82 | executeWithParams(params) |
||
83 | .tap(alerts => { |
||
84 | const ellapsed = new Date().getTime() - start; |
||
85 | emitSuccess(`wow! recompiled and executed in ${ellapsed}ms!`); |
||
86 | io.sockets.emit('update', compileMarkdown(alerts)); |
||
87 | }) |
||
88 | .catch(err => { |
||
89 | emitError(`hot compilation error, baby: ${err.message}`); |
||
90 | io.sockets.emit('failure', err.stack); |
||
91 | }); |
||
92 | }); |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * Starts the stream server using sockets |
||
97 | * |
||
98 | * @param {Object} alerts |
||
99 | * @param {Object} params |
||
100 | * @param {Number} port |
||
101 | * @param {Object} resources |
||
102 | * @return {Promise} |
||
103 | */ |
||
104 | function startServer(alerts, params, port, resources) { |
||
105 | const compiledAlerts = compileMarkdown(alerts); |
||
106 | const app = http.createServer((req, res) => |
||
107 | res.end(resources[req.url] || resources['/index.html'])); |
||
108 | const io = listen(app); |
||
109 | io.on('connection', socket => { |
||
110 | emitInfo(`new session for ${socket.handshake.address}`); |
||
111 | socket.emit('update', compiledAlerts); |
||
112 | socket.on('disconnect', () => { |
||
113 | emitInfo(`disconnected session ${socket.handshake.address}`); |
||
114 | }); |
||
115 | }); |
||
116 | |||
117 | return new Promise(resolve => app.listen(port, emitRungEmoji & resolve)) |
||
118 | .then(~watchChanges(io, params)); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Generates a HTML file compiled from template showing the cards as they will |
||
123 | * be rendered on Rung and opens it in the default browser |
||
124 | * |
||
125 | * @return {Promise} |
||
126 | */ |
||
127 | export default (alerts, params) => getResources() |
||
128 | .tap(startServer(alerts, params, 5001, _)) |
||
0 ignored issues
–
show
|
|||
129 | .tap(() => { |
||
130 | try { |
||
131 | opn('http://localhost:5001/'); |
||
132 | } catch (err) { |
||
133 | // Skip |
||
134 | } |
||
135 | }); |
||
136 |
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.