import fs from 'fs'
import ot from 'dayjs'
import get from 'lodash-es/get.js'
import each from 'lodash-es/each.js'
import size from 'lodash-es/size.js'
import evem from './evem.mjs'
import isestr from './isestr.mjs'
import ispint from './ispint.mjs'
import isbol from './isbol.mjs'
import ispnum from './ispnum.mjs'
import cdbl from './cdbl.mjs'
import haskey from './haskey.mjs'
import fsIsFolder from './fsIsFolder.mjs'
import fsGetFilesWithHashInFolder from './fsGetFilesWithHashInFolder.mjs'
/**
* 後端nodejs偵測指定資料夾下之檔案變化,僅偵測新增與變更檔案,不偵測刪除檔案
*
* Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/fsObserveFiles.test.mjs Github}
* @memberOf wsemi
* @param {String} fd 輸入欲列舉的資料夾字串
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {Integer} [opt.levelLimit=1] 輸入列舉層數限制正整數,設定1為列舉資料夾下第一層的檔案,設定null為無窮遍歷所有檔案,預設1
* @param {String} [opt.type='md5'] 輸入計算HASH方法,預設'md5'
* @param {Number} [opt.interval=60000] 輸入定時器偵測時長正整數,預設60000,為1分鐘
* @param {Boolean} [opt.useReadContent=true] 輸入是否自動讀取檔案內容並用字串儲存至鍵content內布林值,預設true
* @param {Boolean} [opt.useShowLog=false] 輸入是否顯示內建log訊息布林值,預設false
* @returns {Object} 回傳物件,包含ev、run、stop,ev為EventEmitter,run為啟動偵測函數,stop為停止偵測函數
* @example
* //need test in nodejs
*
* let p = fsObserveFiles(fd, { levelLimit: 1, type: 'md5', interval: 60000 })
* console.log(rs)
* p.ev.on('change', (rs) => {
* console.log('rs', rs)
* })
* p.run()
*
*/
function fsObserveFiles(fd, opt = {}) {
//levelLimit
let levelLimit = get(opt, 'levelLimit', '')
if (!ispint(levelLimit)) {
levelLimit = 1
}
//type
let type = get(opt, 'type', '')
if (!isestr(type)) {
type = 'md5'
}
//interval
let m = get(opt, 'interval')
if (!ispnum(m)) {
m = 60 * 1000 //1min
}
m = cdbl(m)
//useReadContent
let useReadContent = get(opt, 'useReadContent')
if (!isbol(useReadContent)) {
useReadContent = true
}
//useShowLog
let useShowLog = get(opt, 'useShowLog')
if (!isbol(useShowLog)) {
useShowLog = false
}
let ev = evem()
let t = null
let b = false
let kp = {}
//core
let core = () => {
//check
if (b) {
return
}
b = true
if (useShowLog) {
console.log('fsObserveFiles run...', ot().format('YYYY-MM-DDTHH:mm:ss'))
}
//check
if (!fsIsFolder(fd)) {
if (useShowLog) {
console.log('fsObserveFiles finish')
}
return
}
//fsGetFilesWithHashInFolder
let fps = fsGetFilesWithHashInFolder(fd, levelLimit, { type })
// console.log('fps', fps)
//rs
let rs = []
each(fps, (v) => {
//check
if (!haskey(kp, v.path)) {
kp[v.path] = {
hash: '',
content: '',
}
}
//hash_ori
let hash_ori = get(kp, v.path, {})
hash_ori = get(hash_ori, 'hash', '')
//hash_new
let hash_new = get(v, 'hash', '')
//check
if (!isestr(hash_new)) {
return true //跳出換下一個
}
//check
if (hash_ori === hash_new) {
return true //跳出換下一個
}
//readFileSync
let content = ''
if (useReadContent) {
content = fs.readFileSync(v.path, 'utf8')
}
//save
kp[v.path] = {
hash: hash_new,
content,
}
//r
let r = {
path: v.path,
}
if (useReadContent) {
r.content = content
}
//push
rs.push(r)
})
// console.log('size(rs)', size(rs))
//check
if (size(rs) > 0) {
//emit
ev.emit('change', rs)
}
b = false
if (useShowLog) {
console.log('fsObserveFiles finish')
}
}
let run = () => {
core()
t = setInterval(() => {
core()
}, m)
}
let stop = () => {
clearInterval(t)
}
return {
ev,
run,
stop,
}
}
export default fsObserveFiles