Socket
Socket
Sign inDemoInstall

@danmasta/walk

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@danmasta/walk - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

lib/walk.js

406

index.js

@@ -1,404 +0,4 @@

const path = require('path');
const fs = require('fs');
const Promise = require('bluebird');
const File = require('./lib/file');
const util = require('./lib/util');
const micromatch = require('micromatch');
const Readable = require('stream').Readable;
const _ = require('lodash');
const Walk = require('./lib/walk');
const readdirAsync = Promise.promisify(fs.readdir);
const statAsync = Promise.promisify(fs.stat);
const readFileAsync = Promise.promisify(fs.readFile);
const accessAsync = Promise.promisify(fs.access);
const constants = {
GLOBS: {
all: '*(../)*(**/)*',
ignore: '*(../)*(**/)(.git|node_modules)',
dot: '*(../)*(**/)!(.)*'
}
};
const defaults = {
cwd: process.cwd(),
root: './',
require: false,
stream: false,
read: false,
sync: false,
contents: false,
buffer: false,
src: constants.GLOBS.all,
dot: true,
ignore: constants.GLOBS.ignore,
cb: _.noop
};
class Walker {
constructor (opts) {
opts = _.defaults(opts, defaults);
if (!opts.dot && opts.src === constants.GLOBS.all) {
opts.src = constants.GLOBS.dot;
}
opts.root = util.stripTrailingSep(path.resolve(opts.cwd, opts.root));
if (opts.require || opts.read === 'require') {
opts.read = 'require';
} else if (opts.stream || opts.read === 'stream') {
opts.read = 'stream';
} else if (opts.read || opts.contents) {
opts.read = 'contents';
}
this.opts = opts;
this.include = null;
this.exclude = null;
if (opts.src) {
this.include = micromatch.matcher(opts.src, { dot: opts.dot });
}
if (opts.ignore) {
this.exclude = micromatch.matcher(opts.ignore, { dot: opts.dot });
}
}
_resolve (str) {
return path.resolve(this.opts.root, str);
}
_contents (file) {
return Promise.resolve().then(() => {
if (this.opts.read === 'require') {
return require(file.path);
} else if (this.opts.read === 'stream') {
return fs.createReadStream(file.path);
} else {
return readFileAsync(file.path).then(buff => {
if (this.opts.buffer) {
return buff;
} else {
return buff.toString();
}
});
}
});
}
_contentsSync (file) {
if (this.opts.read === 'require') {
return require(file.path);
} else if (this.opts.read === 'stream') {
return fs.createReadStream(file.path);
} else {
let buff = fs.readFileSync(file.path);
if (this.opts.buffer) {
return buff;
} else {
return buff.toString();
}
}
}
_walk (str) {
return statAsync(str).then(stat => {
if (stat.isDirectory()) {
return readdirAsync(str).map(name => {
let res = path.resolve(str, name);
let rel = path.relative(this.opts.root, res);
if (!this.exclude || !this.exclude(rel)) {
return this._walk(res);
}
});
} else {
let file = new File({ path: str, stat: stat, cwd: this.opts.cwd, root: this.opts.root });
if (!this.include || this.include(file.relative || file.base)) {
if (this.opts.read) {
return this._contents(file).then(contents => {
file.contents = contents;
this.opts.cb(file);
});
} else {
return this.opts.cb(file);
}
}
}
});
}
_walkSync (str) {
let stat = fs.statSync(str);
if (stat.isDirectory()) {
return fs.readdirSync(str).map(name => {
let res = path.resolve(str, name);
let rel = path.relative(this.opts.root, res);
if (!this.exclude || !this.exclude(rel)) {
return this._walkSync(res);
}
});
} else {
let file = new File({ path: str, stat: stat, cwd: this.opts.cwd, root: this.opts.root });
if (!this.include || this.include(file.relative || file.base)) {
if (this.opts.read) {
file.contents = this._contentsSync(file);
}
return this.opts.cb(file);
}
}
}
walk (str) {
str = this._resolve(str);
return accessAsync(str, fs.constants.F_OK).then(() => {
return str;
}).catch(() => {
return require.resolve(str);
}).then(str => {
return this._walk(str);
});
}
sync (str) {
str = this._resolve(str);
try {
fs.accessSync(str, fs.constants.F_OK);
} catch (err) {
str = require.resolve(str);
}
return this._walkSync(str);
}
}
class WalkStream extends Readable {
constructor (str, opts) {
super({ objectMode: true });
opts = _.assign(opts, { cb: this.push.bind(this) });
this._str = str;
this._walker = new Walker(opts);
}
_read (size) {
if (!this.init) {
this._init();
}
}
_init () {
this.init = true;
if (!this._walker.opts.sync) {
this._walker.walk(this._str).then(() => {
this.push(null);
});
} else {
this._walker.sync(this._str);
this.push(null);
}
}
}
function _walk (str, opts) {
let res = [];
let cb = res.push.bind(res);
let walker = null;
if (_.isFunction(opts && opts.cb)) {
cb = file => {
res.push(opts.cb(file));
};
}
walker = new Walker(_.assign(null, opts, { cb }));
return walker.walk(str).then(() => {
return res;
});
}
function _sync (str, opts) {
let res = [];
let cb = res.push.bind(res);
let walker = null;
if (_.isFunction(opts && opts.cb)) {
cb = file => {
res.push(opts.cb(file));
};
}
walker = new Walker(_.assign(null, opts, { cb, sync: true }));
walker.sync(str);
return res;
}
function _contents (str, opts) {
opts = _.assign(opts, { read: true });
return _walk(str, opts);
}
function _contentsSync (str, opts) {
opts = _.assign(opts, { read: true, sync: true });
return _sync(str, opts);
}
function _require (str, opts) {
opts = _.assign(opts, { require: true });
return _walk(str, opts);
}
function _requireSync (str, opts) {
opts = _.assign(opts, { require: true, sync: true });
return _sync(str, opts);
}
function _stream (str, opts) {
opts = _.assign(opts);
return new WalkStream(str, opts);
}
function _streamSync (str, opts) {
opts = _.assign(opts, { sync: true });
return new WalkStream(str, opts);
}
function _each (str, opts, cb) {
if (_.isFunction(opts)) {
cb = opts;
}
opts = _.assign(opts, { cb: cb });
return _walk(str, opts);
}
function _eachSync (str, opts, cb) {
if (_.isFunction(opts)) {
cb = opts;
}
opts = _.assign(opts, { cb: cb });
return _sync(str, opts);
}
exports = module.exports = _walk;
exports.walk = _walk;
exports.sync = _sync;
exports.Walker = Walker;
exports.contents = _contents;
exports.contents.sync = _contentsSync;
exports.require = _require;
exports.require.sync = _requireSync;
exports.stream = _stream;
exports.stream.sync = _streamSync;
exports.each = _each;
exports.each.sync = _eachSync;
module.exports = exports = Walk.factory();
exports.Walk = Walk;

@@ -68,4 +68,28 @@ const path = require('path');

isBlockDevice () {
return this.stat && this.stat.isBlockDevice();
}
isCharacterDevice () {
return this.stat && this.stat.isCharacterDevice();
}
isFIFO () {
return this.stat && this.stat.isFIFO();
}
isFile () {
return this.stat && this.stat.isFile();
}
isSocket () {
return this.stat && this.stat.isSocket();
}
isEmpty () {
return this.stat && this.stat.size === 0;
}
}
module.exports = File;
{
"name": "@danmasta/walk",
"version": "2.0.1",
"version": "3.0.0",
"author": "Daniel Smith <dannmasta@gmail.com>",

@@ -27,8 +27,8 @@ "description": "Directory and file walking utility for node apps",

"chai": "^4.2.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"mocha": "^6.0.1"
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"mocha": "^8.0.1"
},

@@ -40,6 +40,5 @@ "engines": {

"dependencies": {
"bluebird": "^3.5.3",
"lodash": "^4.17.11",
"micromatch": "^3.1.10"
"lodash": "^4.17.15",
"micromatch": "^4.0.2"
}
}

@@ -6,5 +6,6 @@ # Walk

* Easy to use
* Simple, lightweight, and fast
* Sync, async, streams, and promise api
* Simple filtering with glob pattern matching
* Require file contents or read as stream, buffer, or string
* Require file contents, or read as stream, buffer, or string
* Resolves require-style path strings

@@ -14,5 +15,6 @@ * Normalized file objects with helper methods

* Include and exclude pattern matching options
* Only 2 dependencies: [micromatch](https://github.com/micromatch/micromatch), [lodash](https://github.com/lodash/lodash)
## About
We needed a better way to walk directories and read files during build and/or start time. I wanted an api that was simple, supported glob pattern matching like gulp, and returned objects with a similar format as vinyl. This package allows you to simply read any directory (or file), return an array of objects, and filter results with glob pattern matching. It can also require file contents, read as strings, streams, or buffers, and resolve require-style path strings.
I needed a better way to walk directories and read files during build and/or run time. I wanted an api that was simple, supported glob pattern matching like gulp, and returned objects with a similar format as vinyl. This package allows you to simply read any directory (or file), return an array of objects, and filter results with glob pattern matching. It can also require file contents, or read them as strings, streams, or buffers, and resolve require-style path strings.

@@ -29,2 +31,3 @@ ## Usage

```
By default walk returns a readable stream interface. You can use the methods: `promise()`, `map()`, `each()`, and `sync()` to consume file objects via promises or as a synchronous array.

@@ -38,10 +41,9 @@ ### Options

`stream` | *`boolean`* | If true, `file.contents` will be a `Readable` stream. Default is `false`
`read` | *`boolean\|string`* | If `true`, will read file contents as a buffer or string. If string, accepts either 'require', 'stream', or 'contents'. Default is `false`
`sync` | *`boolean`* | Wether or not we are running in synchronous mode
`read` | *`boolean\|string`* | If `true`, will read file contents as a buffer or string. If string, accepts either `'require'`, `'stream'`, or `'contents'`. Default is `false`
`contents` | *`boolean`* | If true, will read file contents as string. Default is `false`
`buffer` | *`boolean`* | If true, when reading file conents, contents will remain a buffer instead of being converted to a string. Default is `false`
`src` | *`Array\|String\|RegExp`* | [Micromatch pattern](https://github.com/micromatch/micromatch#matcher) for result filtering by including any matches. Can be a path string, glob pattern string, regular expression, or an array of strings. Defaults to `*(../)*(**/)*`
`ignore` | *`Array\|String\|RegExp`* | [Micromatch pattern](https://github.com/micromatch/micromatch#matcher) for result filtering by ignoring any matches. Can be a path string, glob pattern string, regular expression, or an array of strings. Defaults to `*(../)*(**/)(.git|node_modules)`
`ignore` | *`Array\|String\|RegExp`* | [Micromatch pattern](https://github.com/micromatch/micromatch#matcher) for result filtering by ignoring any matches. Can be a path string, glob pattern string, regular expression, or an array of strings. Defaults to `*(../)*(**/)(.git\|node_modules)`
`dot` | *`boolean`* | Whether or not to include dot files when matching. Default is `true`
`cb` | *`function`* | Function to call when flushing a file object. Default is `_.noop`
`resolve` | *`boolean`* | Whether or not to attempt to resolve file paths if not found. Default is `true`

@@ -51,16 +53,13 @@ ### Methods

-----|------------
`walk(path, opts)` | Get a list of files based on specified options. Returns a promise that resolves with an array of file objects
`walk.sync` | Sync version of `walk`. Returns an Array
`contents(path, opts)` | Get the contents of files based on specified options. Returns a promise that resolves with an array of file objects
`contents.sync` | Sync version of `contents`. Returns an Array
`each(path, opts, iteratee)` | Runs an iteratee function for each file based on specified options. Returns a promise that resolves with an array of file objects. Iteratee takes one argument [`file`](#file-objects)
`each.sync` | Sync version of `each`. Returns an Array
`require(path, opts)` | Get the contents of files by requiring them. Returns a promise that resolves with an array of file objects
`require.sync` | Sync version of `require`. Returns an Array
`stream(path, opts)` | Returns a read stream of file objects
`stream.sync` | Sync version of `stream`. Loads file data synchronously. Returns a read stream
`promise()` | Returns a promise that resolves with an array of file objects
`map(fn)` | Runs an iterator function over each file. Returns a promise that resolves with the new `array`
`each(fn)` | Runs an iterator function over each file. Returns a promise that resolves with `undefined`
`sync()` | Walks files and directories in syncronous mode. Returns an array of file objects
`require()` | Enables reading of file contents by requiring them
`stream()` | Enables reading of file contents as a stream
`buffer()` | Enables reading of file contents as a buffer
`contents(str)` | Enables reading of file contents. First parameter can be: `'require'`, `'stream'`, or `'buffer'`
`resolveFilePath(str)` | Resolve a file path relative to options
*Each method takes an optional `path` and `options` param as arguments. The `each` methods also accept an iteratee function as the last argument*
## File Objects

@@ -92,12 +91,22 @@ Each file returned from walk has the following signature

`isSymbolic` | Returns `true` if the file is a [symbolic link](https://nodejs.org/api/fs.html#fs_stats_issymboliclink)
`isBlockDevice` | Returns `true` if the file is a [block device](https://nodejs.org/api/fs.html#fs_stats_isblockdevice)
`isCharacterDevice` | Returns `true` if the file is a [character device](https://nodejs.org/api/fs.html#fs_stats_ischaracterdevice)
`isFIFO` | Returns `true` if the file is a [first-in-first-out (FIFO) pipe](https://nodejs.org/api/fs.html#fs_stats_isfifo)
`isFile` | Returns `true` if the file is a [file](https://nodejs.org/api/fs.html#fs_stats_isfile)
`isSocket` | Returns `true` if the file is a [socket](https://nodejs.org/api/fs.html#fs_stats_issocket)
`isEmpty` | Returns `true` if the file is empty (zero bytes)
## Examples
### Walk
```js
const walk = require('@danmasta/walk');
```
Walk the current working directory and pipe all files to a destination stream
```js
walk('./').pipe(myDestinationStream());
```
Walk the current working directory, exclude all `.json` files
```js
walk('./', { src: '**/*.!(json)' }).then(res => {
walk('./', { src: '**/*.!(json)' }).promise().then(res => {
console.log('files:', res);

@@ -108,3 +117,3 @@ });

```js
walk('./config', { src: '**/*.json' }).then(res => {
walk('./config', { src: '**/*.json' }).promise().then(res => {
console.log('files:', res);

@@ -115,3 +124,3 @@ });

```js
walk('/usr/local').then(res => {
walk('/usr/local').promise().then(res => {
console.log('files:', res);

@@ -121,16 +130,20 @@ });

### Contents
Read the contents of all `pug` files in `./views`
```js
walk.contents('./views', { src: '**/*.pug' }).then(res => {
walk('./views', { src: '**/*.pug', contents: true }).promise().then(res => {
console.log('templates:', res);
});
```
Read the contents of all `pug` files in `./views` as a `buffer`
```js
walk('./views', { src: '**/*.pug', buffer: true }).promise().then(res => {
console.log('templates:', res);
});
```
### Each
Require all `js` files in the `./routes` directory and run a callback for each one
```js
walk.each('./routes', { src: '**/*.js', require: true }, route => {
walk('./routes', { src: '**/*.js', require: true }).each(route => {
app.use(route());
}).then(res => {
}).then(() => {
console.log('all routes loaded');

@@ -140,10 +153,5 @@ });

### Synchronous Methods
To use the sync version of any method just append `.sync` to the end of the method name
Load all templates from the `./views` directory synchronously
```js
const walk = require('@danmasta/walk');
```
Load all templates from the `./views` directory
```js
const templates = walk.contents.sync('./views', { src: '**/*.pug' });
const templates = walk('./views', { src: '**/*.pug' }).sync();
console.log('templates:', templates);

@@ -150,0 +158,0 @@ ```

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc