-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.js
More file actions
126 lines (109 loc) · 3.98 KB
/
build.js
File metadata and controls
126 lines (109 loc) · 3.98 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
#! /usr/bin/env node
const chalk = require('chalk')
const tee = require('tee')
const stripAnsi = require('strip-ansi')
const { PassThrough } = require('stream')
const readline = require('readline')
const concurrently = require('concurrently')
const { assert } = require('chai')
const { spawn } = require('child_process')
// Parse build flags and environment variables
let watchMode = false
process.argv.slice(2).forEach(flag => {
switch (flag) {
case '--watch': return watchMode = true
default: throw new Error(`Unrecognized flag "${flag}"`)
}
})
// Colors!
const blue = chalk.hex('#164176')
const pink = chalk.hex('#fa759e')
const green = chalk.hex('#6FCF97')
const gold = chalk.hex('#FFCA00')
const purple = chalk.hex('#8000800')
const normalText = blue
const emphasis = pink.bold
const scssCommand = (entrypoint, color) => ({
name: color(`scss:${entrypoint}`),
command: `./node_modules/.bin/sass scss/${entrypoint}.scss css/${entrypoint}.css ${watchMode ? '--watch' : ''}`
})
// The commands to run, give each a color so that they appear distinct in the terminal
const commands = [
scssCommand('common', green),
scssCommand('index', green),
scssCommand('welcome', green),
scssCommand('privacy-tos', green),
{
name: gold(`typescript`),
command: `./node_modules/.bin/tsc ${watchMode ? '--watch --preserveWatchOutput' : ''}`
},
{
name: purple(`views`),
command: `npm run views ${watchMode ? ' -- --watch' : ''}`
},
]
// In watch mode, run a server as a child process, forwarding stdout and stderr
let server
function startServer() {
server = spawn('npm', ['start'])
server.stdout.pipe(process.stdout)
server.stderr.pipe(process.stderr)
}
function restartServer() {
console.log('restarting server...')
server.on('exit', startServer)
server.kill()
server = null // Unset the reference to the server so that we don't try to restart it again if another command is completed before the server is killed
}
// Create an output stream that writes to process.stdout
// and to a PassThrough stream that can be read from to determine command progress.
const passThrough = new PassThrough()
const outputStream = tee(process.stdout, passThrough)
// Log that the build is starting
console.log(
'🛠 ' +
normalText('Building the Roar! server ') +
(watchMode ? emphasis('in watch mode ') : '') +
'\n'
)
// Run the build. If any commands fail, kill the others and exit with its exit code
concurrently(commands, { outputStream, prefix: '{name} {time}', killOthers: ['failure'] }).catch(results => {
const { exitCode } = results.find(result => result.exitCode !== 0 && typeof result.exitCode === 'number')
process.exit(exitCode)
})
// On a successful build, let the user know.
// When not in watch mode, destroy the passThrough as we no longer have any use for it.
// When in watch mode, start the server.
function onSuccessfulBuild() {
const toLog = watchMode
? 'First build successful! Continuing to watch files...'
: 'Build successful!'
console.log(`\n🎉 ${emphasis(toLog)}\n`)
if (!watchMode) {
passThrough.destroy()
} else {
startServer()
}
}
// Keep track of how many commands are done and callback onSuccessfulBuild when they are all complete
let commandsDone = 0
const onCommandCompleted = () => {
commandsDone++
if (commandsDone === commands.length) {
onSuccessfulBuild()
} else if (server) {
restartServer()
}
}
// Read the passThrough stream line by line and call back onCommandCompleted when
// we detect that certain tasks completed successfully. In watch mode, commands
// are done when they read Compiled|created. Otherwise, they are only done with
// they exit with code 0
readline.createInterface(passThrough).on('line', line => {
const commandCompletedRegex = watchMode
? /(^.+ Found 0 errors\. Watching for file changes\.$)|(^.+ Compiled .+\.scss to .+\.css\.$)|(^.+ Compiled \.jsx files in \/views to \/html$)/
: /^.* exited with code 0/
if (commandCompletedRegex.test(stripAnsi(line))) {
onCommandCompleted()
}
})