parent
529ed63ddb
commit
1900dc5ba2
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
/node_modules/
|
||||
/coverage/
|
|
@ -0,0 +1,4 @@
|
|||
tests/
|
||||
test/
|
||||
*.test.js
|
||||
testing/
|
|
@ -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": {
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
### File System Watcher Class
|
||||
#### a uCOMmandIt Utiltiy Function
|
|
@ -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 }
|
|
@ -0,0 +1 @@
|
|||
**/node_modules/**
|
|
@ -0,0 +1,5 @@
|
|||
tests/
|
||||
test/
|
||||
*.test.js
|
||||
testing/
|
||||
example/
|
|
@ -0,0 +1 @@
|
|||
this was modified some moreddddddd
|
|
@ -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()
|
||||
// // })
|
||||
//
|
||||
// }
|
Loading…
Reference in New Issue