110 lines
3.4 KiB
JavaScript
110 lines
3.4 KiB
JavaScript
|
const sleep = x => new Promise(res => setTimeout(() => res(), x * 1000))
|
||
|
|
||
|
;(async () => {
|
||
|
const { spawn } = require('node:child_process')
|
||
|
const ora = (await import('ora')).default
|
||
|
|
||
|
class Builder {
|
||
|
constructor() {
|
||
|
this.spinner = ora('Starting build').start()
|
||
|
this.contextMaxLines = 3
|
||
|
this.contextLines = Array(this.contextMaxLines).fill('')
|
||
|
this.allLines = []
|
||
|
this.steps = []
|
||
|
this.renderLines()
|
||
|
}
|
||
|
|
||
|
pushLine(line) {
|
||
|
if ( this.contextLines.length >= this.contextMaxLines ) this.contextLines = this.contextLines.slice(1)
|
||
|
this.contextLines.push(String(line).trimEnd())
|
||
|
this.allLines.push(String(line).trimEnd())
|
||
|
this.renderLines()
|
||
|
}
|
||
|
|
||
|
renderLines() {
|
||
|
this.spinner.suffixText = `\n--\n${this.contextLines.join('\n')}\n--`
|
||
|
}
|
||
|
|
||
|
addStep(name, callback) {
|
||
|
this.steps.push({ name, callback })
|
||
|
}
|
||
|
|
||
|
async build() {
|
||
|
for ( let i = 0; i < this.steps.length; i += 1 ) {
|
||
|
const step = this.steps[i]
|
||
|
this.spinner.text = `(${i+1}/${this.steps.length}) ${step.name}`
|
||
|
await step.callback(this)
|
||
|
}
|
||
|
|
||
|
this.spinner.suffixText = ''
|
||
|
this.spinner.succeed('Built successfully')
|
||
|
}
|
||
|
|
||
|
async executeOrExit(prog, ...args) {
|
||
|
try {
|
||
|
return await this.execute(prog, ...args)
|
||
|
} catch (e) {
|
||
|
this.spinner.suffixText = ''
|
||
|
this.spinner.fail(`${this.spinner.text} - ${e.message}`)
|
||
|
console.log(this.allLines.join('\n'))
|
||
|
process.exit(1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
execute(prog, ...args) {
|
||
|
this.pushLine(`> ${prog} ${args.join(' ')}`)
|
||
|
|
||
|
const cmd = spawn(prog, args)
|
||
|
let output = ''
|
||
|
|
||
|
cmd.stdout.on('data', data => {
|
||
|
output += data
|
||
|
String(data).split('\n').map(x => this.pushLine(x))
|
||
|
})
|
||
|
cmd.stderr.on('data', data => {
|
||
|
output += data
|
||
|
String(data).split('\n').map(x => this.pushLine(x))
|
||
|
})
|
||
|
|
||
|
return new Promise((res, rej) => {
|
||
|
cmd.on('close', code => {
|
||
|
if ( code ) {
|
||
|
return rej(new Error('Process exited with code: ' + code))
|
||
|
} else {
|
||
|
res(output.trim())
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const b= new Builder
|
||
|
|
||
|
b.addStep(
|
||
|
'Remove old build files',
|
||
|
b => b.executeOrExit('./node_modules/.bin/rimraf', 'lib'),
|
||
|
)
|
||
|
|
||
|
b.addStep(
|
||
|
'Build back-end TypeScript code',
|
||
|
b => b.executeOrExit('./node_modules/.bin/tsc', '-p', 'tsconfig.node.json'),
|
||
|
)
|
||
|
|
||
|
b.addStep(
|
||
|
'Copy resources to output bundle',
|
||
|
b => b.executeOrExit('./node_modules/.bin/fse', 'copy', '--all', '--dereference', '--preserveTimestamps', '--keepExisting=false', '--quiet', '--errorOnExist=false', 'src/app/resources', 'lib/app/resources'),
|
||
|
)
|
||
|
|
||
|
b.addStep(
|
||
|
'Build front-end TypeScript code',
|
||
|
b => b.executeOrExit('./node_modules/.bin/tsc', '-p', 'tsconfig.client.json'),
|
||
|
)
|
||
|
|
||
|
b.addStep(
|
||
|
'Create front-end output bundle',
|
||
|
b => b.executeOrExit('./node_modules/.bin/webpack', '--config', 'webpack.config.js'),
|
||
|
)
|
||
|
|
||
|
await b.build()
|
||
|
})();
|