Initial commit

master
Sven Slootweg 3 years ago
commit 19aaa47cbb

@ -0,0 +1,3 @@
{
"extends": "@joepie91/eslint-config"
}

1
.gitignore vendored

@ -0,0 +1 @@
node_modules

@ -0,0 +1,22 @@
"use strict";
const Promise = require("bluebird");
const pipe = require("@promistream/pipe");
const walkFolder = require(".");
const map = require("@promistream/map");
const filter = require("@promistream/filter");
const find = require("@promistream/find");
return Promise.try(() => {
return pipe([
walkFolder(".", {
// NOTE: Make sure that your predicate always includes the initial path, or nothing will happen
throughStream: filter((path) => path === "." || path.includes("node_modules"))
}),
map((item) => item.path),
find((path) => path.includes("bluebird"))
]).read();
}).then((result) => {
console.log(result);
});

@ -0,0 +1,88 @@
/* eslint-disable no-undef */
"use strict";
const Promise = require("bluebird");
const fs = require("fs").promises;
const path = require("path");
const unreachable = require("@joepie91/unreachable")("@promistream/walk-folder");
const pipe = require("@promistream/pipe");
const simpleQueue = require("@promistream/simple-queue");
const parallelize = require("@promistream/parallelize");
const mapFilter = require("@promistream/map-filter");
const { validateArguments } = require("@validatem/core");
const required = require("@validatem/required");
const isBoolean = require("@validatem/is-boolean");
const isString = require("@validatem/is-string");
const defaultTo = require("@validatem/default-to");
// TODO: Change API to also provide access to the corresponding stat object, not just the path?
module.exports = function createWalkFolderStream(_rootPath, _options) {
let [ rootPath, options ] = validateArguments(arguments, {
rootPath: [ required, isString ],
options: [ defaultTo({}), {
linear: [ defaultTo(false), isBoolean ],
followSymlinks: [ defaultTo(true), isBoolean ],
throughStream: [ defaultTo(null) ] // FIXME: either null or isPromistream, take implementation from `pipe`
}]
});
// linear: Whether to walk the tree linearly (breadth-first) instead of randomly. This will make output deterministic, usually at the cost of being slower. On some filesystems that deal poorly with concurrent I/O, this may actually be a little faster.
// linear -> sort + no parallelize, random -> parallelize infinity unordered
let queue = simpleQueue([ rootPath ]);
let seenInodes = new Set(); // NOTE: Used for detecting and avoiding infinite loops through eg. symlinks
function queueDirectoryContents(targetPath) {
return Promise.try(() => {
return fs.readdir(targetPath);
}).then((entries) => {
if (options.linear === true) {
entries.sort(); // To make the output deterministic
}
return entries;
}).map((item) => {
return queue.push(path.join(targetPath, item));
});
}
let statStream = mapFilter((targetPath) => {
return Promise.try(() => {
if (options.followSymlinks === true) {
return fs.stat(targetPath);
} else {
return fs.lstat(targetPath);
}
}).then((stats) => {
if (stats.ino == null) {
throw new unreachable("Stats without inode encountered");
} else if (!seenInodes.has(stats.ino)) {
seenInodes.add(stats.ino);
return Promise.try(() => {
if (stats.isDirectory()) {
return queueDirectoryContents(targetPath);
}
}).then(() => {
return { path: targetPath, stats: stats };
});
} else {
return mapFilter.NoValue;
}
}).catch((error) => {
console.error(targetPath, error);
});
});
return pipe([
queue.stream,
options.throughStream,
statStream,
(options.linear !== false)
? parallelize(Infinity, { ordered: false })
: null
]);
};

@ -0,0 +1,28 @@
{
"name": "@promistream/walk-folder",
"version": "0.1.0",
"main": "index.js",
"repository": "http://git.cryto.net/promistream/walk-folder.git",
"author": "Sven Slootweg <admin@cryto.net>",
"license": "WTFPL OR CC0-1.0",
"dependencies": {
"@joepie91/unreachable": "^1.0.0",
"@promistream/map-filter": "^0.1.0",
"@promistream/parallelize": "^0.1.1",
"@promistream/pipe": "^0.1.6",
"@promistream/simple-queue": "^0.1.0",
"@validatem/core": "^0.3.15",
"@validatem/default-to": "^0.1.0",
"@validatem/is-boolean": "^0.1.1",
"@validatem/is-string": "^1.0.0",
"@validatem/required": "^0.1.1",
"bluebird": "^3.7.2"
},
"devDependencies": {
"@joepie91/eslint-config": "^1.1.0",
"@promistream/filter": "^0.1.1",
"@promistream/find": "^0.1.0",
"@promistream/map": "^0.1.1",
"eslint": "^7.30.0"
}
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save