155 lines
4.5 KiB
JavaScript
155 lines
4.5 KiB
JavaScript
|
const EventEmitter = require('events')
|
||
|
const fs = require('fs')
|
||
|
const path = require('path')
|
||
|
|
||
|
const rollup = require('rollup')
|
||
|
const loadAndParseConfigFile = require('rollup/dist/loadConfigFile')
|
||
|
|
||
|
const Builder = require('./Builder.cjs')
|
||
|
|
||
|
const rootDir = path.join(__dirname, '../../../../')
|
||
|
|
||
|
const pkgJson = require(path.join(rootDir, 'package.json'))
|
||
|
|
||
|
const mochaTsRelativeDir = pkgJson.directories['mocha-ts']
|
||
|
const mochaTsDir = path.join(rootDir, mochaTsRelativeDir)
|
||
|
|
||
|
class RollupBuilder extends Builder {
|
||
|
constructor ({ name, configPath, tempDir }) {
|
||
|
super(path.join(tempDir, 'semaphore'), name)
|
||
|
this.tempDir = tempDir
|
||
|
this.configPath = configPath
|
||
|
this.firstBuild = true
|
||
|
}
|
||
|
|
||
|
async start ({ watch = false, commonjs = false }) {
|
||
|
await super.start()
|
||
|
|
||
|
this.watch = watch
|
||
|
this.commonjs = commonjs
|
||
|
this.watchedModule = commonjs ? pkgJson.exports['.'].node.require : pkgJson.exports['.'].node.import
|
||
|
|
||
|
const { options } = await loadAndParseConfigFile(this.configPath)
|
||
|
|
||
|
// Instead of compiling all the outputs let us just take the one we are using with mocha (either cjs or esm)
|
||
|
const rollupOptions = options.filter(bundle => {
|
||
|
const file = (bundle.output[0].dir !== undefined)
|
||
|
? path.join(bundle.output[0].dir, bundle.output[0].entryFileNames)
|
||
|
: bundle.output[0].file
|
||
|
return file === path.join(rootDir, this.watchedModule)
|
||
|
})[0]
|
||
|
if (rollupOptions.output.length > 1) {
|
||
|
rollupOptions.output = rollupOptions.output[0]
|
||
|
}
|
||
|
|
||
|
this.builder = new RollupBundler({ rollupOptions, watch: this.watch, watchedModule: this.watchedModule })
|
||
|
|
||
|
this.builder.on('event', event => {
|
||
|
let updateSemaphore = true
|
||
|
switch (event.code) {
|
||
|
case 'START':
|
||
|
this.emit('busy')
|
||
|
if (this.firstBuild === true) {
|
||
|
this.emit('message', 'building your module...')
|
||
|
} else {
|
||
|
this.emit('message', 'file changes detected. Rebuilding module files...')
|
||
|
}
|
||
|
break
|
||
|
|
||
|
case 'BUNDLE_END':
|
||
|
if (event.result) event.result.close()
|
||
|
break
|
||
|
|
||
|
case 'END':
|
||
|
if (event.result) event.result.close()
|
||
|
|
||
|
// fs.mkdirSync(path.join(this.tempDir, path.dirname(this.watchedModule)), { recursive: true })
|
||
|
// // console.log(path.join(this.tempDir, path.dirname(this.watchedModule)))
|
||
|
// fs.copyFileSync(this.watchedModule, path.join(this.tempDir, this.watchedModule))
|
||
|
|
||
|
if (this.firstBuild) {
|
||
|
this.firstBuild = false
|
||
|
updateSemaphore = false
|
||
|
}
|
||
|
this.emit('ready', updateSemaphore)
|
||
|
break
|
||
|
|
||
|
case 'ERROR':
|
||
|
if (event.result) event.result.close()
|
||
|
this.emit('error', event.error)
|
||
|
fs.writeFileSync(path.join(rootDir, this.watchedModule), '', 'utf8')
|
||
|
// fs.writeFileSync(path.join(this.tempDir, this.watchedModule), '', 'utf8')
|
||
|
this.emit('ready')
|
||
|
break
|
||
|
|
||
|
default:
|
||
|
this.emit('busy')
|
||
|
break
|
||
|
}
|
||
|
})
|
||
|
|
||
|
this.builder.start()
|
||
|
|
||
|
return await this.ready()
|
||
|
}
|
||
|
|
||
|
async close () {
|
||
|
await super.close()
|
||
|
this.builder.close()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class RollupBundler extends EventEmitter {
|
||
|
constructor ({ rollupOptions, watchedModule, watch = false }) {
|
||
|
super()
|
||
|
this.rollupOptions = rollupOptions
|
||
|
this.watch = watch
|
||
|
this.watchedModule = watchedModule
|
||
|
}
|
||
|
|
||
|
async start () {
|
||
|
if (this.watch === true) {
|
||
|
this.watcher = rollup.watch(this.rollupOptions)
|
||
|
|
||
|
this.watcher.on('event', event => {
|
||
|
this.emit('event', event)
|
||
|
})
|
||
|
} else {
|
||
|
if (!fs.existsSync(path.join(rootDir, this.watchedModule))) {
|
||
|
await this._bundle()
|
||
|
} else {
|
||
|
this.emit('event', { code: 'END', noBuild: true })
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async _bundle () {
|
||
|
this.emit('event', { code: 'START' })
|
||
|
for (const optionsObj of [].concat(this.rollupOptions)) {
|
||
|
try {
|
||
|
const bundle = await rollup.rollup(optionsObj)
|
||
|
try {
|
||
|
await Promise.all(optionsObj.output.map(bundle.write))
|
||
|
this.emit('event', { code: 'BUNDLE_END' })
|
||
|
} catch (error) {
|
||
|
this.emit('event', { code: 'ERROR', error })
|
||
|
}
|
||
|
} catch (error) {
|
||
|
this.emit('event', { code: 'ERROR', error })
|
||
|
}
|
||
|
}
|
||
|
this.emit('event', { code: 'END' })
|
||
|
}
|
||
|
|
||
|
close () {
|
||
|
if (this.watcher !== undefined) this.watcher.close()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exports.RollupBuilder = RollupBuilder
|
||
|
exports.rollupBuilder = new RollupBuilder({
|
||
|
name: 'rollup',
|
||
|
configPath: path.join(rootDir, pkgJson.directories.build, 'rollup.config.js'),
|
||
|
tempDir: mochaTsDir
|
||
|
})
|