Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use async fs functions #124

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 22 additions & 23 deletions lib/is.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var fs = require('fs');
var fs = require('fs-extra');
var path = require('path');
var os = require('os');

Expand All @@ -7,16 +7,13 @@ function matchObject(item, str) {
=== '[object ' + str + ']';
}

function checkStat(name, fn) {
try {
return fn(name);
} catch (err) {
if (/^(ENOENT|EPERM|EACCES)$/.test(err.code)) {
if (err.code !== 'ENOENT') {
console.warn('Warning: Cannot access %s', name);
}
return false;
function checkStat(err) {
if (/^(ENOENT|EPERM|EACCES)$/.test(err.code)) {
if (err.code !== 'ENOENT') {
console.warn('Warning: Cannot access %s', name);
}
return false;
} else {
throw err;
}
}
Expand Down Expand Up @@ -49,26 +46,28 @@ var is = {
number: function(item) {
return matchObject(item, 'Number');
},
exists: function(name) {
return fs.existsSync(name);
exists: async function(name) {
return fs.access(name, fs.constants.F_OK)
.then(() => true)
.catch(() => false)
},
file: function(name) {
return checkStat(name, function(n) {
return fs.statSync(n).isFile()
});
file: async function(name) {
return fs.stat(name)
.then((stats) => stats.isFile())
.catch(checkStat)
},
samePath: function(a, b) {
return path.resolve(a) === path.resolve(b);
},
directory: function(name) {
return checkStat(name, function(n) {
return fs.statSync(n).isDirectory()
});
directory: async function(name) {
return fs.stat(name)
.then((stats) => stats.isDirectory())
.catch(checkStat)
},
symbolicLink: function(name) {
return checkStat(name, function(n) {
return fs.lstatSync(n).isSymbolicLink();
});
return fs.stat(name)
.then((stats) => stats.isSymbolicLink())
.catch(checkStat)
},
windows: function() {
return os.platform() === 'win32';
Expand Down
4 changes: 2 additions & 2 deletions lib/watch.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ declare function watch(pathName: PathName, options: Options) : Watcher;
declare function watch(pathName: PathName, callback: Callback): Watcher;
declare function watch(pathName: PathName, options: Options, callback: Callback): Watcher;

type EventType = 'update' | 'remove';
export type EventType = 'update' | 'remove';
type Callback = (eventType: EventType, filePath: string) => any;
type PathName = string | Array<string>;
type FilterReturn = boolean | symbol;
Expand Down Expand Up @@ -60,7 +60,7 @@ type Options = {
delay ?: number;
};

declare interface Watcher extends FSWatcher {
export interface Watcher extends FSWatcher {
/**
* Returns `true` if the watcher has been closed.
*/
Expand Down
146 changes: 83 additions & 63 deletions lib/watch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var fs = require('fs');
var fs = require('fs-extra');
var path = require('path');
var util = require('util');
var events = require('events');
Expand Down Expand Up @@ -52,15 +52,17 @@ function guard(fn) {
}
}

function composeMessage(names) {
return names.map(function(n) {
return is.exists(n)
async function composeMessage(names) {
const ps = names.map((n) => is.exists(n))
const exists = await Promise.all(ps)
return names.map((n, index) => {
return exists[index]
? [EVENT_UPDATE, n]
: [EVENT_REMOVE, n];
});
})
}

function getMessages(cache) {
async function getMessages(cache) {
var filtered = unique(cache);

// Saving file from an editor? If so, assuming the
Expand All @@ -76,9 +78,13 @@ function getMessages(cache) {
return c.replace(reg, '');
}));
if (dup) {
filtered = filtered.filter(function(m) {
var existing = filtered.map(function(m) {
return is.exists(m);
});
await Promise.all(existing);
filtered = filtered.filter((v, index) => {
return existing[index]
})
}
}

Expand All @@ -92,16 +98,18 @@ function debounce(info, fn) {
if (!is.number(delay)) {
delay = 200;
}
function handle() {
getMessages(cache).forEach(function(msg) {
async function handle() {
const cacheClone = [...cache]
cache = [];
timer = null;
const messages = await getMessages(cacheClone)
messages.forEach(function(msg) {
msg[1] = Buffer.from(msg[1]);
if (encoding !== 'buffer') {
msg[1] = msg[1].toString(encoding);
}
fn.apply(null, msg);
});
timer = null;
cache = [];
}
return function(rawEvt, name) {
cache.push(name);
Expand All @@ -126,27 +134,24 @@ function createDupsFilter() {
}
}

function getSubDirectories(dir, fn, done = function() {}) {
if (is.directory(dir)) {
fs.readdir(dir, function(err, all) {
if (err) {
// don't throw permission errors.
if (/^(EPERM|EACCES)$/.test(err.code)) {
console.warn('Warning: Cannot access %s.', dir);
} else {
throw err;
}
}
else {
all.forEach(function(f) {
var sdir = path.join(dir, f);
if (is.directory(sdir)) fn(sdir);
});
done();
async function getSubDirectories(dir, fn) {
if (!(await is.directory(dir))) return;
try {
const all = await fs.readdir(dir);
const subDirs = all.map(async function(f) {
var sdir = path.join(dir, f);
if (await (is.directory(sdir))) {
fn(sdir);
}
});
} else {
done();
return Promise.allSettled(subDirs);
} catch(err) {
// don't throw permission errors.
if (/^(EPERM|EACCES)$/.test(err.code)) {
console.warn('Warning: Cannot access %s.', dir);
} else {
throw err;
}
}
}

Expand Down Expand Up @@ -218,7 +223,8 @@ Watcher.prototype.close = function(fullPath) {
}
getSubDirectories(fullPath, function(fpath) {
self.close(fpath);
});
})
.catch((err) => self.emit('error', err))
}
else {
Object.keys(self.watchers).forEach(function(fpath) {
Expand Down Expand Up @@ -291,20 +297,23 @@ Watcher.prototype.add = function(watcher, info) {
hasNativeRecursive(function(has) {
if (!has) {
var fullPath = path.resolve(name);
// remove watcher on removal
if (!is.exists(name)) {
self.close(fullPath);
}
// watch new created directory
else {
var shouldWatch = is.directory(name)
&& !self.watchers[fullPath]
&& shouldNotSkip(name, info.options.filter);

if (shouldWatch) {
self.watchDirectory(name, info.options);
}
}
is.exists(name)
.then(async exists => {
if (!exists) {
// remove watcher on removal
self.close(fullPath);
} else {
// watch new created directory
var shouldWatch = !self.watchers[fullPath]
&& await is.directory(name)
&& shouldNotSkip(name, info.options.filter);

if (shouldWatch) {
self.watchDirectory(name, info.options);
}
}
})
.catch((err) => self.emit('error', err))
}
});
}
Expand Down Expand Up @@ -413,7 +422,9 @@ Watcher.prototype.watchDirectory = function(dir, options, fn, counter = nullCoun
if (shouldNotSkip(d, options.filter)) {
self.watchDirectory(d, options, null, counter);
}
}, counter());
})
.then(() => counter())
.catch((err) => self.emit('error', err))
}

done();
Expand Down Expand Up @@ -470,12 +481,16 @@ function watch(fpath, options, fn) {
fpath = fpath.toString();
}

if (!is.array(fpath) && !is.exists(fpath)) {
process.nextTick(function() {
watcher.emit('error',
new Error(fpath + ' does not exist.')
);
});
if (!is.array(fpath)) {
is.exists(fpath).then((result) => {
if (!result) {
process.nextTick(function() {
watcher.emit('error',
new Error(fpath + ' does not exist.')
);
});
}
})
}

if (is.string(options)) {
Expand Down Expand Up @@ -513,17 +528,22 @@ function watch(fpath, options, fn) {
}));
}

if (is.file(fpath)) {
watcher.watchFile(fpath, options, fn);
emitReady(watcher);
}

else if (is.directory(fpath)) {
var counter = semaphore(function () {
emitReady(watcher);
});
watcher.watchDirectory(fpath, options, fn, counter);
}
is.file(fpath)
.then((isFile) => {
if (isFile) {
watcher.watchFile(fpath, options, fn);
emitReady(watcher);
} else {
return is.directory(fpath).then((isDirectory) => {
if (!isDirectory) return
var counter = semaphore(function () {
emitReady(watcher);
});
watcher.watchDirectory(fpath, options, fn, counter);
})
}
})
.catch((err) => self.emit('error', err))

return watcher.expose();
}
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
"engines": {
"node": ">=6"
},
"dependencies": {
"fs-extra": "^10.1.0"
},
"devDependencies": {
"fs-extra": "^7.0.1",
"mocha": "^5.2.0"
}
}