walk.js/create.js

74 lines
1.8 KiB
JavaScript
Raw Permalink Normal View History

2020-12-09 22:58:53 +00:00
"use strict";
2020-12-09 11:10:56 +00:00
2020-12-09 22:58:53 +00:00
const fs = require("fs").promises;
const Walk = require("./walk.js");
const path = require("path");
const _withFileTypes = { withFileTypes: true };
const _noopts = {};
const _pass = (err) => err;
2020-12-09 11:10:56 +00:00
2020-12-09 22:58:53 +00:00
// a port of Go's filepath.Walk
2020-12-09 11:48:55 +00:00
Walk.create = function (opts) {
if (!opts) {
opts = _noopts;
2020-12-09 11:10:56 +00:00
}
2020-12-09 11:48:55 +00:00
// a port of Go's filepath.Walk
const _walk = async (pathname, walkFunc, _dirent) => {
let err;
2020-12-09 11:10:56 +00:00
2020-12-09 11:48:55 +00:00
// special case of the very first run
if (!_dirent) {
_dirent = pathname;
2020-12-09 11:10:56 +00:00
}
2020-12-09 11:48:55 +00:00
// the first run, or if false === withFileTypes
if ("string" === typeof _dirent) {
let _name = path.basename(path.resolve(pathname));
2020-12-09 22:58:53 +00:00
_dirent = await fs.lstat(pathname).catch(_pass);
2020-12-09 11:48:55 +00:00
if (_dirent instanceof Error) {
err = _dirent;
} else {
_dirent.name = _name;
}
2020-12-09 11:10:56 +00:00
}
2020-12-09 11:48:55 +00:00
// run the user-supplied function and either skip, bail, or continue
2020-12-09 22:58:53 +00:00
err = await walkFunc(err, pathname, _dirent).catch(_pass);
2020-12-09 11:48:55 +00:00
if (false === err || Walk.skipDir === err) {
2020-12-09 11:10:56 +00:00
return;
}
2020-12-09 11:48:55 +00:00
if (err instanceof Error) {
throw err;
2020-12-09 11:10:56 +00:00
}
2020-12-09 11:48:55 +00:00
// "walk does not follow symbolic links"
if (!_dirent || !_dirent.isDirectory()) {
return;
2020-12-09 11:10:56 +00:00
}
2020-12-09 11:48:55 +00:00
// lightweight dirents or full lstat
let _readdirOpts;
if (!opts.withFileStats) {
_readdirOpts = _withFileTypes;
}
2020-12-09 11:10:56 +00:00
2020-12-09 11:48:55 +00:00
// TODO check if the error is "not a directory"
// (and thus allow false === opts.withFileTypes)
2020-12-09 22:58:53 +00:00
let result = await fs.readdir(pathname, _readdirOpts).catch(_pass);
2020-12-09 11:48:55 +00:00
if (result instanceof Error) {
return walkFunc(result, pathname, _dirent);
2020-12-09 11:10:56 +00:00
}
2020-12-09 11:48:55 +00:00
if (opts.sort) {
result = opts.sort(result);
}
for (let entity of result) {
await _walk(path.join(pathname, entity.name || entity), walkFunc, entity);
}
};
2020-12-09 11:10:56 +00:00
return _walk;
};
2020-12-09 22:58:53 +00:00
module.exports = Walk;