134 lines
4.1 KiB
JavaScript
134 lines
4.1 KiB
JavaScript
// native imports
|
|
import { EventEmitter as Emitter } from 'events'
|
|
import path from 'path'
|
|
// third party imports
|
|
import { watch } from 'chokidar'
|
|
// local imports
|
|
import ignores from './read-lines'
|
|
// UCI imports
|
|
import logger from '@uci/logger'
|
|
let log = {}
|
|
|
|
|
|
const READY_TIMEOUT = 2000
|
|
|
|
class Watcher extends Emitter {
|
|
constructor(opts={}) {
|
|
super()
|
|
log = logger({ package:'@uci/sync', class:'Watcher', file:'src/watcher.js'})
|
|
opts.unlinkDir = Object.hasOwnProperty(opts.unlinkDir) ? opts.unlinkDir : true
|
|
this.opts = opts
|
|
this._ignored = []
|
|
this._ready=false
|
|
this.watching=false
|
|
return this
|
|
}
|
|
|
|
async init(opts) {
|
|
return new Promise(async (resolve, reject) => {
|
|
opts = opts || this.opts
|
|
if (opts.excludeFrom) await this.getIgnoreLists(opts.excludeFrom)
|
|
if (opts.ignoreList) await this.getIgnoreLists(opts.ignoreList)
|
|
if (opts.source) {
|
|
opts.ignored = opts.ignored ? [...this._ignored,...opts.ignored] : this._ignored
|
|
log.debug({ignored:opts.ignored, msg:'all ignores'})
|
|
this._watcher = watch(opts.source,opts)
|
|
this._watcher.on('error', error => {
|
|
log.error({error:error, msg:'Watcher error'})
|
|
})
|
|
this._watcher.on('ready', () => {
|
|
clearTimeout(readyTimeout)
|
|
log.info('initial scan sucessful, ready to start')
|
|
this._ready=true
|
|
this.opts = opts // save options
|
|
resolve()
|
|
})
|
|
let readyTimeout = setTimeout(() =>{
|
|
log.fatal({options:opts, timeout:READY_TIMEOUT, msg:'Timeout: unabled to complete initial scan'})
|
|
reject('timeout during intial scan')
|
|
},READY_TIMEOUT)
|
|
}
|
|
else {
|
|
log.fatal('MUST provide a source directory(s) option to watch')
|
|
reject('no source provided')
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
async start(opts) {
|
|
if(this.watching) {
|
|
log.warn(`watching aleady running for ${this.opts.source}`)
|
|
return false
|
|
}
|
|
if (!this._watcher) await this.init(opts)
|
|
if (this._ready) {
|
|
log.info(`now watching ${this.opts.source}`)
|
|
this._watcher.removeAllListeners() // just in case
|
|
this.watching = true
|
|
// define command listen handler
|
|
const handler =
|
|
(type, f) => {
|
|
log.debug(`file ${f} was ${type}`)
|
|
// convert this to a plugin/hook so it's not specific
|
|
const fname = path.basename(f)
|
|
if ( fname.toLowerCase() === 'package.json')
|
|
if (type !=='modified') {
|
|
this.emit('error',new Error('package.json was added or removed, ignoring sync and reinstall'))
|
|
return
|
|
} else{
|
|
this.emit('install', f)
|
|
}
|
|
// user might want to run debounce on the listener for this event
|
|
this.emit('changed', {file:f, type:type})
|
|
} // end handler
|
|
|
|
this._watcher
|
|
.on('add', handler.bind(this, 'added'))
|
|
.on('change', handler.bind(this, 'modified'))
|
|
.on('unlink', handler.bind(this, 'removed'))
|
|
if(this.opts.unlinkDir) this._watcher.on('unlinkDir', handler.bind(this, 'dir-deleted'))
|
|
if(this.opts.addDir) this._watcher.on('addDir', handler.bind(this, 'dir-added'))
|
|
} else {
|
|
log.warn('watcher is not ready to start, check options and try again')
|
|
return new Error('not ready to start check configuration')
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
if(this.watching) {
|
|
this.watching = false
|
|
this._watcher.close()
|
|
}
|
|
else log.warn('not watching, nothing to close')
|
|
}
|
|
|
|
remove() {
|
|
this.stop()
|
|
delete(this._watcher)
|
|
this._ready=false
|
|
}
|
|
|
|
async restart(opts) {
|
|
this.remove()
|
|
await this.start(opts)
|
|
}
|
|
|
|
async getIgnoreLists(lists) {
|
|
// console.log('ignore lists', lists)
|
|
if (typeof lists === 'string') lists=[lists]
|
|
let ignored = await ignores(lists)
|
|
// console.log('==ignores from lists', ignored)
|
|
this._ignored = [...this._ignored,...ignored]
|
|
// console.log(this._ignored)
|
|
}
|
|
|
|
addIgnore(ignore) {
|
|
Array.isArray(ignore) ? this._ignored.push(...ignore) : this._ignored.push(ignore)
|
|
}
|
|
clearAllIgnore() { this._ignored = [] }
|
|
|
|
}
|
|
|
|
export default Watcher
|