eltro/lib/watch/has-native-recursive.mjs

114 lines
2.3 KiB
JavaScript

import fs from 'fs'
import os from 'os'
import path from 'path'
import * as is from './is.mjs'
let IS_SUPPORT
let TEMP_DIR = os.tmpdir && os.tmpdir()
|| process.env.TMPDIR
|| process.env.TEMP
|| process.cwd()
function TempStack() {
this.stack = []
}
TempStack.prototype.create = function(type, base) {
let name = path.join(base,
'node-watch-' + Math.random().toString(16).substr(2)
)
this.stack.push({ name: name, type: type })
return name
}
TempStack.prototype.write = function(/* file */) {
for (let i = 0; i < arguments.length; ++i) {
fs.writeFileSync(arguments[i], ' ')
}
}
TempStack.prototype.mkdir = function(/* dirs */) {
for (let i = 0; i < arguments.length; ++i) {
fs.mkdirSync(arguments[i])
}
}
TempStack.prototype.cleanup = function(fn) {
try {
let temp
while ((temp = this.stack.pop())) {
let type = temp.type
let name = temp.name
if (type === 'file' && is.file(name)) {
fs.unlinkSync(name)
}
else if (type === 'dir' && is.directory(name)) {
fs.rmdirSync(name)
}
}
}
finally {
if (is.func(fn)) fn()
}
}
let pending = false
export default function hasNativeRecursive(fn) {
if (!is.func(fn)) {
return false
}
if (IS_SUPPORT !== undefined) {
return fn(IS_SUPPORT)
}
if (!pending) {
pending = true
}
// check again later
else {
return setTimeout(function() {
hasNativeRecursive(fn)
}, 300)
}
let stack = new TempStack()
let parent = stack.create('dir', TEMP_DIR)
let child = stack.create('dir', parent)
let file = stack.create('file', child)
stack.mkdir(parent, child)
let options = { recursive: true }
let watcher
try {
watcher = fs.watch(parent, options)
} catch (e) {
if (e.code == 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM') {
return fn(IS_SUPPORT = false)
} else {
throw e
}
}
if (!watcher) {
return false
}
let timer = setTimeout(function() {
watcher.close()
stack.cleanup(function() {
fn(IS_SUPPORT = false)
})
}, 200)
watcher.on('change', function(evt, name) {
if (path.basename(file) === path.basename(name)) {
watcher.close()
clearTimeout(timer)
stack.cleanup(function() {
fn(IS_SUPPORT = true)
})
}
})
stack.write(file)
}