setup for test working but needs to include listener for change
master
David Kebler 2019-02-16 11:40:48 -08:00
parent 529ed63ddb
commit 1900dc5ba2
10 changed files with 234 additions and 1 deletions

37
.eslintrc.js Normal file
View File

@ -0,0 +1,37 @@
module.exports = {
"ecmaFeatures": {
"modules": true,
"spread" : true,
"restParams" : true
},
// "plugins": [
// "unicorn"
// ],
"env": {
"es6": true,
"node": true,
"mocha": true
},
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"extends": "eslint:recommended",
"rules": {
"indent": [
"error",
2
],
// "unicorn/no-array-instanceof": "error",
"no-console": 0,
"semi": ["error", "never"],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
]
}
}

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/node_modules/
/coverage/

4
.npmignore Normal file
View File

@ -0,0 +1,4 @@
tests/
test/
*.test.js
testing/

View File

@ -1,6 +1,6 @@
{
"name": "@uci-utils/watcher",
"version": "0.2.1",
"version": "0.2.2",
"description": "File System Watcher Class that emits events",
"main": "src/watcher.js",
"scripts": {

2
readme.md Normal file
View File

@ -0,0 +1,2 @@
### File System Watcher Class
#### a uCOMmandIt Utiltiy Function

134
src/watcher.js Normal file
View File

@ -0,0 +1,134 @@
// native imports
import { EventEmitter as Emitter } from 'events'
import path from 'path'
// third party imports
import { watch } from 'chokidar'
// UCI imports
import ignores from '@uci-utils/read-lines'
import logger from '@uci-utils/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
log.debug({options:opts, msg:'intializing watch with options'})
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
export { Watcher }

1
test/repo/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/node_modules/**

5
test/repo/.npmignore Normal file
View File

@ -0,0 +1,5 @@
tests/
test/
*.test.js
testing/
example/

1
test/repo/dontwatch.js Normal file
View File

@ -0,0 +1 @@
this was modified some moreddddddd

47
test/watcher.test.js Normal file
View File

@ -0,0 +1,47 @@
import Watcher from '../src/watcher'
// import to from 'await-to-js'
import { expect } from 'chai'
import { it } from 'mocha'
describe('Watcher Class Testing ',async ()=> {
// let log = logger({})
before(async () => {
// log = logger({ package:'@uci/sync', id: 'sync-test' })
let options = {source:'./test/repo', ignored:['**/dontwatch.js'],ignoreList:['./test/repo/.gitignore']}
let watcher = new Watcher(options)
await watcher.start()
watcher.on('changed',
// debounce(
(change) => {
console.log(`======= file ${change.file} was ${change.type} ==========`)
}
)
})
it('can watch for file delete' , async function () {
// let [err,res] = await to(remote.exec('cd /opt && pwd'))
// if (err) {
// log.info('error running command aborting test', err)
// return
// }
// log.info(`result of remote command ${res.command} => ${res.reply.toString().trim()}`)
expect('test', 'test failed').to.equal('test')
})
})
// function hooks(remote) {
//
// // beforeEach(async() => {
// // await someasyncfunctiontodobeforeeachtest()
// // })
//
// // after(async() => {
// // await someasyncfunctiontodoaftereeachtest()
// // })
//
// }