From f903ef7071d487cf6788c2654db52f417a0767e9 Mon Sep 17 00:00:00 2001 From: "kebler.net" Date: Tue, 29 Jun 2021 07:38:59 -0700 Subject: [PATCH] 0.6.1 fix: catch and warn if remove watcher is called but no watcher was started. --- example/example.js | 38 +++++++-------- package.json | 2 +- src/watcher.js | 114 +++++++++++++++++++++++---------------------- 3 files changed, 78 insertions(+), 76 deletions(-) diff --git a/example/example.js b/example/example.js index a2fe05e..933ded5 100644 --- a/example/example.js +++ b/example/example.js @@ -1,29 +1,29 @@ import Watcher from '../src/watcher.js' -import onDeath from 'ondeath' +import onDeath from 'ondeath' -const USE_CUSTOM_HANDLER=true -const DEBOUNCE=0 -const READY_TIMEOUT=null +const USE_CUSTOM_HANDLER = true +const DEBOUNCE = 0 +const READY_TIMEOUT = null -; + ; (async () => { let options = { - source:'./example/repo/**', - ignored:['**/dontwatch.js'], - ignoreList:['./example/repo/.gitignore'], + source: './example/repo/**', + ignored: ['**/dontwatch.js'], + ignoreList: ['./example/repo/.gitignore'], debounce: DEBOUNCE, - readyTimeout:READY_TIMEOUT + readyTimeout: READY_TIMEOUT } let watcher = new Watcher(options) - watcher.on('ready', (state,opts) =>{ - console.log('watched files indexed and ready??',state) + watcher.on('ready', (state, opts) => { + console.log('watched files indexed and ready??', state) if (opts) console.dir(opts) }) - watcher.on('watching', (state, opts) =>{ - console.log('watcher is active and listening for changes?',state) + watcher.on('watching', (state, opts) => { + console.log('watcher is active and listening for changes?', state) if (opts) console.dir(opts) }) @@ -31,10 +31,10 @@ const READY_TIMEOUT=null await watcher.start( // {ignored:'**/another'} ) - + if (USE_CUSTOM_HANDLER) { watcher.registerHandler( - function handler (type, f) { + function handler(type, f) { this.emit('custom', f, type) } // end handler ) @@ -43,20 +43,20 @@ const READY_TIMEOUT=null console.log(`custom handler ======= file ${file} was ${type} ==========`) }) } - + // default handler event is `changed` else watcher.on('changed', - (file,type) => { + (file, type) => { console.log(`======= file ${file} was ${type} ==========`) }) - onDeath( () => { + onDeath(() => { console.log('\nHe\'s dead Jim') watcher.remove() }) })().catch(err => { - console.error('FATAL: UNABLE TO START SYSTEM!\n',err) + console.error('FATAL: UNABLE TO START SYSTEM!\n', err) }) diff --git a/package.json b/package.json index 6af267f..eeb3c52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@uci-utils/watcher", - "version": "0.6.0", + "version": "0.6.1", "description": "File System Watcher Class that emits events", "main": "src/watcher.js", "type": "module", diff --git a/src/watcher.js b/src/watcher.js index 0bff0bf..83e82ea 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -13,42 +13,42 @@ let log = {} const READY_TIMEOUT = 10000 //default class Watcher extends Emitter { - constructor(opts={}) { + constructor(opts = {}) { super() - log = logger({ package:'@uci-utils/watcher', class:'Watcher', file:'src/watcher.js'}) + log = logger({ package: '@uci-utils/watcher', class: 'Watcher', file: 'src/watcher.js' }) opts.unlinkDir = 'unlinkDir' in opts ? opts.unlinkDir : true // delete file even on by default this.opts = opts this.timeout = process.env.READY_TIMEOUT || opts.readyTimeout || READY_TIMEOUT this._ignored = opts.ignored ? (Array.isArray(opts.ignored) ? opts.ignored : opts.ignored.split(',')) : [] this.handler = opts.handler || _handler - this._ready=false - this._watching=false + this._ready = false + this._watching = false return this } - get watching () { + get watching() { return this._watching } - get ready () { + get ready() { return this._ready } - registerHandler(func,opts) { - opts = Object.assign({},this.opts,opts) - if (!this._watcher) return 'failed: watcher not initialized' - if (typeof func ==='function') this.handler = func + registerHandler(func, opts) { + opts = Object.assign({}, this.opts, opts) + if (!this._watcher) return 'failed: watcher not initialized' + if (typeof func === 'function') this.handler = func else if (func) opts = func - opts = Object.assign({},this.opts,opts) + opts = Object.assign({}, this.opts, opts) let handler if (opts.debounce) - handler = debounce((type, file) => { + handler = debounce((type, file) => { log.debug(`waited : ${opts.debounce}ms before calling handler`) log.info('debounced handler, only last event is emitted') - this.handler.call(this,type,file) - },{wait:opts.debounce}) + this.handler.call(this, type, file) + }, { wait: opts.debounce }) else - handler= (type,file) => {this.handler.call(this,type,file)} + handler = (type, file) => { this.handler.call(this, type, file) } this._watcher.removeAllListeners() @@ -62,55 +62,57 @@ class Watcher extends Emitter { // reset the error event since it got scrubbed this._watcher.on('error', error => { - const msg ='chokidar watcher error' - log.error({error:error, msg:msg}) - this.emit('error',msg,error) + const msg = 'chokidar watcher error' + log.error({ error: error, msg: msg }) + this.emit('error', msg, error) }) } - async start(opts={}) { - if(this._watching) { + async start(opts = {}) { + if (this._watching) { log.warn(`watching aleady running for ${opts.source || this.opts.source}`) return false } if (!this._watcher) opts = await this._init(opts) if (this._ready) { this.emit('ready', true, opts) - log.trace({watching:this._watcher.getWatched(),msg:'initial files watched'}) + log.trace({ watching: this._watcher.getWatched(), msg: 'initial files watched' }) log.info(`now watching ${opts.source || this.opts.source}`) if (this.registerHandler(opts)) { log.fatal('watcher was not initialzed so could not register handler') return new Error('watcher was not initialzed so could not register handler') } this._watching = true - this.emit('watching',true,opts) + this.emit('watching', true, opts) } else { - const msg ='watcher is not ready to start, check options and try again' + const msg = 'watcher is not ready to start, check options and try again' log.fatal(msg) - this.emit('error',msg) + this.emit('error', msg) return new Error('not ready to start check configuration options') } } stop() { - if(this._watching) { + if (this._watching) { this._watching = false this._watcher.close() - this.emit('watching',false) + this.emit('watching', false) } else log.warn('not watching, nothing to stop') } remove() { - this.stop() - this._watcher.removeAllListeners() - delete(this._watcher) - this._ready=false - this.emit('ready',false) + if (this._watcher) { + this.stop() + this._watcher.removeAllListeners() + delete (this._watcher) + } else log.warn('no watcher started nothing to remove') + this._ready = false + this.emit('ready', false) } - async restart(opts,force) { - if (typeof opts ==='boolean') {force=opts,opts={}} + async restart(opts, force) { + if (typeof opts === 'boolean') { force = opts, opts = {} } this.stop() await this.start(opts) } @@ -121,37 +123,37 @@ class Watcher extends Emitter { // private methods - async _init(opts={}) { + async _init(opts = {}) { if (!opts.overwrite) { await this._fetchIgnoreLists(this.opts.excludeFrom) await this._fetchIgnoreLists(this.opts.ignoreList) } - await this._fetchIgnoreLists(opts.excludeFrom,opts.overwrite) - await this._fetchIgnoreLists(opts.ignoreList,opts.overwrite) + await this._fetchIgnoreLists(opts.excludeFrom, opts.overwrite) + await this._fetchIgnoreLists(opts.ignoreList, opts.overwrite) if (!opts.ignored) opts.ignored = [] opts.ignored = Array.isArray(opts.ignored) ? opts.ignored : opts.ignored.split(',') - opts.ignored = opts.overwrite ? opts.ignored : [...this._ignored,...opts.ignored] - opts = Object.assign({},this.opts,opts) // now that ingnore arrays are dealt with merge options + opts.ignored = opts.overwrite ? opts.ignored : [...this._ignored, ...opts.ignored] + opts = Object.assign({}, this.opts, opts) // now that ingnore arrays are dealt with merge options return new Promise(async (resolve, reject) => { - log.debug({options:opts, msg:'intializing watch with options'}) + log.debug({ options: opts, msg: 'intializing watch with options' }) if (opts.source) { // create chokidar watcher - this._watcher = watch(opts.source,opts) + this._watcher = watch(opts.source, opts) this._watcher.once('error', error => { - log.error({error:error, msg:'Watcher error'}) - reject({error:error, msg:'Watcher error'}) + log.error({ error: error, msg: 'Watcher error' }) + reject({ error: error, msg: 'Watcher error' }) }) this._watcher.once('ready', () => { clearTimeout(readyTimeout) log.info('initial scan sucessful, ready to start') - this._ready=true + this._ready = true resolve(opts) }) log.debug(`initial scanning, timeout in ${this.timeout}ms`) - let readyTimeout = setTimeout(() =>{ - log.fatal({options:opts, timeout:this.timeout, msg:'Timeout: unable to complete initial scan'}) + let readyTimeout = setTimeout(() => { + log.fatal({ options: opts, timeout: this.timeout, msg: 'Timeout: unable to complete initial scan' }) reject('timeout during initial scan, maybe increase ready timeout') - },this.timeout) + }, this.timeout) } else { log.fatal('MUST provide a source directory(s) option to watch') @@ -160,11 +162,11 @@ class Watcher extends Emitter { }) } - async _fetchIgnoreLists(lists,overwrite) { - if (typeof lists === 'string') lists=[lists] + async _fetchIgnoreLists(lists, overwrite) { + if (typeof lists === 'string') lists = [lists] if (!Array.isArray(lists)) return // no lists let ignored = await readIgnoreLists(lists) - this._ignored = overwrite ? ignored : [...this._ignored,...ignored] + this._ignored = overwrite ? ignored : [...this._ignored, ...ignored] } @@ -172,21 +174,21 @@ class Watcher extends Emitter { } //end class // default handler -function _handler (type, f) { +function _handler(type, f) { log.debug(`file ${f} was ${type}`) const fname = path.basename(f) - if ( fname.toLowerCase() === 'package.json' && path.dirname(f)=== this.opts.source.replace(/\/$/, '')) - if (type !=='modified') { + if (fname.toLowerCase() === 'package.json' && path.dirname(f) === this.opts.source.replace(/\/$/, '')) + if (type !== 'modified') { const msg = `a package.json in root of ${this.opts.source} was added or removed` log.warning(msg) - this.emit('warning',f,msg) + this.emit('warning', f, msg) return - } else{ + } else { this.emit('install', f) } // user might want to run debounce on the listener for this event - log.debug({file:f, type:type, msg:'file system changed, emitting'}) - this.emit('changed', f,type) + log.debug({ file: f, type: type, msg: 'file system changed, emitting' }) + this.emit('changed', f, type) } // end handler export default Watcher