Issues (23)

src/live.js (1 issue)

Labels
Severity
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
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

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.

Loading history...
129
    .tap(() => {
130
        try {
131
            opn('http://localhost:5001/');
132
        } catch (err) {
133
            // Skip
134
        }
135
    });
136