@danmasta/walk
Advanced tools
Comparing version 4.1.0 to 4.2.0
const Walk = require('./lib/walk'); | ||
const walk = Walk.factory(); | ||
exports = module.exports = Walk.factory(); | ||
exports = module.exports = walk; | ||
exports.walk = walk; | ||
exports.Walk = Walk; |
137
lib/file.js
const path = require('path'); | ||
const fs = require('fs/promises'); | ||
const { createReadStream, createWriteStream } = require('fs'); | ||
const util = require('./util'); | ||
const { BOM } = require('./constants'); | ||
const _ = require('lodash'); | ||
const util = require('./util'); | ||
const fs = require('fs'); | ||
const constants = require('./constants'); | ||
@@ -22,11 +23,2 @@ const defaults = { | ||
class FileError extends Error { | ||
constructor (str) { | ||
super(str); | ||
Error.captureStackTrace(this, FileError); | ||
this.name = 'FileError'; | ||
this.code = 'FILEERROR'; | ||
} | ||
} | ||
class File { | ||
@@ -36,3 +28,3 @@ | ||
_.defaults(this, opts, defaults); | ||
Object.assign(this, util.defaults(opts, defaults)); | ||
@@ -46,3 +38,3 @@ this.root = this.root ? util.stripTrailingSep(this.root) : this.cwd; | ||
if (!this.path) { | ||
throw new File.FileError('Path or relative field is required'); | ||
throw new util.FileError('Path or relative field is required'); | ||
} | ||
@@ -60,3 +52,3 @@ | ||
createReadStream (opts) { | ||
return fs.createReadStream( | ||
return createReadStream( | ||
this.path, | ||
@@ -68,3 +60,3 @@ _.defaults(opts, { encoding: this.encoding }) | ||
createWriteStream (opts) { | ||
return fs.createWriteStream( | ||
return createWriteStream( | ||
this.path, | ||
@@ -75,4 +67,4 @@ _.defaults(opts, { encoding: this.encoding }) | ||
append (data, opts) { | ||
return fs.promises.appendFile( | ||
async append (data, opts) { | ||
return fs.appendFile( | ||
this.path, | ||
@@ -84,4 +76,4 @@ data, | ||
read (opts) { | ||
return fs.promises.readFile( | ||
async read (opts) { | ||
return fs.readFile( | ||
this.path, | ||
@@ -92,5 +84,5 @@ _.defaults(opts, { encoding: this.encoding }) | ||
readAsString (opts) { | ||
async readAsString (opts) { | ||
if ((!opts || opts && !opts.encoding) && !this.encoding) { | ||
return Promise.reject(new File.FileError('Encoding is required to read as string')); | ||
throw new util.FileError('Encoding is required to read as string'); | ||
} else { | ||
@@ -101,3 +93,3 @@ return this.read(opts); | ||
readAsBuffer (opts) { | ||
async readAsBuffer (opts) { | ||
return this.read( | ||
@@ -108,12 +100,12 @@ _.assign(opts, { encoding: null }) | ||
readStr (...args) { | ||
async readStr (...args) { | ||
return this.readAsString(...args); | ||
} | ||
readBuf (...args) { | ||
async readBuf (...args) { | ||
return this.readAsBuffer(...args); | ||
} | ||
write (data, opts) { | ||
return fs.promises.writeFile( | ||
async write (data, opts) { | ||
return fs.writeFile( | ||
this.path, | ||
@@ -129,2 +121,55 @@ data, | ||
async import () { | ||
switch (this.ext) { | ||
case '.json': | ||
return import(this.path, { assert: { type: 'json' }}); | ||
default: | ||
return import(this.path); | ||
} | ||
} | ||
async requireOrImport () { | ||
switch (this.ext) { | ||
case '.json': | ||
if (util.isEsmMode()) { | ||
return this.import(); | ||
} else { | ||
return this.require(); | ||
} | ||
case '.js': | ||
case '.cjs': | ||
if (util.isEsmMode()) { | ||
return this.import(); | ||
} else { | ||
try { | ||
return this.require(); | ||
} catch (err) { | ||
if (err.code === 'ERR_REQUIRE_ESM' || err.code === 'ERR_REQUIRE_ASYNC_MODULE') { | ||
return this.import(); | ||
} | ||
throw err; | ||
} | ||
} | ||
case '.mjs': | ||
return this.import(); | ||
default: | ||
throw new util.FileError('File type not supported for require or import: %s', this.ext); | ||
} | ||
} | ||
async requireImportOrRead () { | ||
try { | ||
return this.requireOrImport(); | ||
} catch (err) { | ||
if (err.code === 'ERR_FILE') { | ||
return this.read(); | ||
} | ||
throw err; | ||
} | ||
} | ||
isModule () { | ||
return util.isModule(this.contents); | ||
} | ||
isBuffer () { | ||
@@ -142,2 +187,6 @@ return util.isBuffer(this.contents); | ||
isNil () { | ||
return util.isNil(this.contents); | ||
} | ||
isString () { | ||
@@ -151,3 +200,3 @@ return typeof this.contents === 'string'; | ||
isSymbolic () { | ||
isSymbolicLink () { | ||
return this.stat && this.stat.isSymbolicLink(); | ||
@@ -180,37 +229,27 @@ } | ||
getEncodingFromBOM () { | ||
async getEncodingFromBOM () { | ||
let buff = Buffer.alloc(4); | ||
let enc = undefined; | ||
let fd = await fs.open(this.path, 'r'); | ||
return fs.promises.open(this.path, 'r').then(fd => { | ||
await fd.read(buff, 0, 4, 0); | ||
await fd.close(); | ||
return fd.read(buff, 0, 4, 0).then(() => { | ||
return fd.close(); | ||
}); | ||
_.some(BOM, (val, key) => { | ||
if (buff.indexOf(val) === 0) { | ||
return enc = key; | ||
} | ||
}); | ||
}).then(() => { | ||
return enc; | ||
_.some(File.constants.BOM, (val, key) => { | ||
if (buff.indexOf(val) === 0) { | ||
return enc = key; | ||
} | ||
}); | ||
return enc; | ||
}); | ||
} | ||
static get FileError () { | ||
return FileError; | ||
return util.FileError; | ||
} | ||
static get constants () { | ||
return constants; | ||
} | ||
} | ||
module.exports = File; |
180
lib/util.js
const path = require('path'); | ||
const isBuffer = require('buffer').Buffer.isBuffer; | ||
const os = require('os'); | ||
const fs = require('fs'); | ||
const _ = require('lodash'); | ||
const format = require('util').format; | ||
class WalkError extends Error { | ||
constructor (...args) { | ||
super(format(...args)); | ||
Error.captureStackTrace(this, this.constructor); | ||
this.name = this.constructor.name; | ||
this.code = this.constructor.code; | ||
} | ||
static get code () { | ||
return 'ERR_WALK'; | ||
} | ||
} | ||
class NotFoundError extends WalkError { | ||
constructor (path) { | ||
super('File or Directory Not Found: %s', path); | ||
this.path = path; | ||
} | ||
static get code () { | ||
return 'ERR_WALK_NOT_FOUND'; | ||
} | ||
} | ||
class NotResolvedError extends WalkError { | ||
constructor (path) { | ||
super('Unable to Resolve File or Directory: %s', path); | ||
this.path = path; | ||
} | ||
static get code () { | ||
return 'ERR_WALK_NOT_RESOLVED'; | ||
} | ||
} | ||
class FileError extends Error { | ||
constructor (...args) { | ||
super(format(...args)); | ||
Error.captureStackTrace(this, this.constructor); | ||
this.name = this.constructor.name; | ||
this.code = this.constructor.code; | ||
} | ||
static get code () { | ||
return 'ERR_FILE'; | ||
} | ||
} | ||
// Resolve file path with support for home char | ||
function resolvePath (str, dir) { | ||
if (str[0] === '~') { | ||
return path.normalize(path.join(os.homedir(), str.slice(1))); | ||
} else { | ||
if (dir) { | ||
return path.resolve(dir, str); | ||
} else { | ||
return path.resolve(str); | ||
} | ||
} | ||
} | ||
async function resolvePathIfExists (str, dir, resolve) { | ||
let path; | ||
try { | ||
path = resolvePath(str, dir); | ||
await fs.promises.access(path, fs.constants.F_OK); | ||
return path; | ||
} catch (err) { | ||
if (resolve) { | ||
try { | ||
return require.resolve(path); | ||
} catch (err) { | ||
throw new NotResolvedError(str); | ||
} | ||
} else { | ||
throw new NotFoundError(str); | ||
} | ||
} | ||
} | ||
function resolvePathIfExistsSync (str, dir, resolve) { | ||
let path; | ||
try { | ||
path = resolvePath(str, dir); | ||
fs.accessSync(path, fs.constants.F_OK); | ||
return path; | ||
} catch (err) { | ||
if (resolve) { | ||
try { | ||
return require.resolve(path); | ||
} catch (err) { | ||
throw new NotResolvedError(str); | ||
} | ||
} else { | ||
throw new NotFoundError(str); | ||
} | ||
} | ||
} | ||
function normalize (str) { | ||
@@ -17,11 +116,7 @@ return str && path.normalize(str); | ||
function isStream (obj) { | ||
let pipe = obj && obj.pipe; | ||
if (pipe && typeof pipe === 'function') { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
return false; | ||
} | ||
@@ -33,2 +128,70 @@ | ||
function defaults (...args) { | ||
let accumulator = {}; | ||
function iterate (res, obj, def) { | ||
_.forOwn(obj, (val, key) => { | ||
if (_.has(def, key)) { | ||
if (_.isPlainObject(def[key])) { | ||
res[key] = iterate(_.toPlainObject(res[key]), val, def[key]); | ||
} else { | ||
if (res[key] === undefined) { | ||
res[key] = val; | ||
} | ||
} | ||
} | ||
}); | ||
return res; | ||
} | ||
args.map(obj => { | ||
iterate(accumulator, obj, args.at(-1)); | ||
}); | ||
return accumulator; | ||
} | ||
function isNil (val) { | ||
return val == null; | ||
} | ||
function notNil (val) { | ||
return val != null; | ||
} | ||
function each (arr, fn) { | ||
if (Array.isArray(arr) || arr instanceof Map || arr instanceof Set) { | ||
arr.forEach(fn); | ||
} else { | ||
fn(arr, 0); | ||
} | ||
} | ||
function eachNotNil (arr, fn) { | ||
each(arr, (val, key) => { | ||
if (notNil(val)) { | ||
fn(val, key); | ||
} | ||
}); | ||
} | ||
// Test if running in esm or commonjs mode | ||
function isEsmMode () { | ||
return typeof module === 'undefined'; | ||
} | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#module_namespace_object | ||
function isModule (obj) { | ||
return notNil(obj) && obj[Symbol.toStringTag] === 'Module'; | ||
} | ||
exports.WalkError = WalkError; | ||
exports.NotFoundError = NotFoundError; | ||
exports.NotResolvedError = NotResolvedError; | ||
exports.FileError = FileError; | ||
exports.resolvePath = resolvePath; | ||
exports.resolvePathIfExists = resolvePathIfExists; | ||
exports.resolvePathIfExistsSync = resolvePathIfExistsSync; | ||
exports.normalize = normalize; | ||
@@ -40,1 +203,8 @@ exports.stripStartingSep = stripStartingSep; | ||
exports.unixify = unixify; | ||
exports.defaults = defaults; | ||
exports.isNil = isNil; | ||
exports.notNil = notNil; | ||
exports.each = each; | ||
exports.eachNotNil = eachNotNil; | ||
exports.isEsmMode = isEsmMode; | ||
exports.isModule = isModule; |
325
lib/walk.js
const Readable = require('stream').Readable; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const os = require('os'); | ||
const micromatch = require('micromatch'); | ||
const _ = require('lodash'); | ||
const File = require('./file'); | ||
const FileResolver = require('./resolver'); | ||
const util = require('./util'); | ||
const constants = require('./constants'); | ||
const _ = require('lodash'); | ||
const defaults = { | ||
cwd: process.cwd(), | ||
root: './', | ||
src: constants.GLOBS.all, | ||
dot: true, | ||
ignore: constants.GLOBS.ignore, | ||
encoding: 'utf8', | ||
objectMode: true, | ||
resolve: true | ||
}; | ||
class NotFoundError extends Error { | ||
constructor (str) { | ||
let msg = `File or Directory Not Found: ${str}`; | ||
super(msg); | ||
Error.captureStackTrace(this, NotFoundError); | ||
this.name = 'NotFoundError'; | ||
this.code = 'PATHNOTFOUND'; | ||
this.path = str; | ||
} | ||
} | ||
class NotResolvedError extends Error { | ||
constructor (str) { | ||
let msg = `Unable to Resolve File or Directory: ${str}`; | ||
super(msg); | ||
Error.captureStackTrace(this, NotResolvedError); | ||
this.name = 'NotResolvedError'; | ||
this.code = 'PATHNOTRESOLVED'; | ||
this.path = str; | ||
} | ||
} | ||
class Walk extends Readable { | ||
@@ -56,72 +19,24 @@ | ||
if (paths) { | ||
if (!_.isArray(paths)) { | ||
if (!opts.root) { | ||
opts.root = paths; | ||
paths = []; | ||
} else { | ||
paths = [paths]; | ||
} | ||
} | ||
} else { | ||
paths = []; | ||
if (!opts.paths) { | ||
opts.paths = paths; | ||
} | ||
opts = _.defaults(opts, defaults); | ||
super({ objectMode: true }); | ||
if (!opts.dot && opts.src === constants.GLOBS.all) { | ||
opts.src = constants.GLOBS.dot; | ||
} | ||
this.reading = false; | ||
this.resolver = new this.constructor.FileResolver(opts); | ||
this.opts = opts; | ||
this.include = null; | ||
this.exclude = null; | ||
opts.root = util.stripTrailingSep(this.getRootWalkPath(opts.root)); | ||
if (opts.src) { | ||
this.include = micromatch.matcher(opts.src, { dot: opts.dot }); | ||
} | ||
if (opts.ignore) { | ||
this.exclude = micromatch.matcher(opts.ignore, { dot: opts.dot }); | ||
} | ||
this.queue = []; | ||
this.paths = paths; | ||
this.pending = 0; | ||
this.inFlight = 0; | ||
// Should be true until we push at least one file on each iteration | ||
this.shouldRead = true; | ||
if (!this.paths.length) { | ||
this.paths.push(this.opts.root); | ||
} | ||
} | ||
_read () { | ||
if (!this.inFlight && !this.pending) { | ||
this.handleRead(); | ||
} | ||
} | ||
handleRead () { | ||
if (this.canRead()) { | ||
this.readFromQueue().then(() => { | ||
if (this.shouldRead) { | ||
this.handleRead(); | ||
async _read () { | ||
if (!this.reading) { | ||
this.reading = true; | ||
let file; | ||
while ((file = await this.resolver.next()) !== null) { | ||
if (!this.push(file)) { | ||
this.reading = false; | ||
break; | ||
} | ||
}); | ||
} else { | ||
if (this.paths.length) { | ||
this.addPathIfExists(this.paths.shift()).then(() => { | ||
if (this.shouldRead) { | ||
this.handleRead(); | ||
} | ||
}); | ||
} else if (this.isEmpty()) { | ||
} | ||
if (file === null) { | ||
this.push(null); | ||
@@ -132,170 +47,9 @@ } | ||
canRead () { | ||
return this.queue.length > 0; | ||
} | ||
async iterate (fn, res) { | ||
isEmpty () { | ||
return !this.inFlight && !this.pending && !this.queue.length && !this.paths.length; | ||
} | ||
let file; | ||
resolvePathFromHomeOrRoot (str) { | ||
if (str && str[0] === '~') { | ||
return path.normalize(path.join(os.homedir(), str.slice(1))); | ||
} else { | ||
return path.resolve(this.opts.root, str); | ||
} | ||
} | ||
resolvePathFromHomeOrCWD (str) { | ||
if (str && str[0] === '~') { | ||
return path.normalize(path.join(os.homedir(), str.slice(1))); | ||
} else { | ||
return path.resolve(this.opts.cwd, str); | ||
} | ||
} | ||
// Resolve path from user home or cwd | ||
// Verifies path exists or throws error | ||
getRootWalkPath (str) { | ||
let res = this.resolvePathFromHomeOrCWD(str); | ||
let stat = null; | ||
try { | ||
stat = fs.statSync(res); | ||
if (stat.isDirectory() || stat.isFile()) { | ||
return res; | ||
} else { | ||
this.destroy(new Walk.NotFoundError(res)); | ||
} | ||
} catch (err) { | ||
if (this.opts.resolve) { | ||
try { | ||
return require.resolve(res); | ||
} catch (err) { | ||
this.destroy(new Walk.NotResolvedError(res)); | ||
} | ||
} else { | ||
this.destroy(new Walk.NotFoundError(res)); | ||
} | ||
} | ||
} | ||
addPathIfExists (str) { | ||
str = this.resolvePathFromHomeOrRoot(str); | ||
this.pending++; | ||
return fs.promises.access(str, fs.constants.F_OK).then(() => { | ||
this.pending--; | ||
this.pushToQueue(str); | ||
}).catch(err => { | ||
if (this.opts.resolve) { | ||
try { | ||
this.pending--; | ||
this.pushToQueue(require.resolve(str)); | ||
} catch (err) { | ||
this.destroy(new Walk.NotResolvedError(str)); | ||
} | ||
} else { | ||
this.pending--; | ||
this.destroy(new Walk.NotFoundError(str)); | ||
} | ||
}); | ||
} | ||
pushToQueue (str) { | ||
return this.queue.push(str); | ||
} | ||
readFromQueue () { | ||
return this.walkFileOrDir(this.queue.shift()); | ||
} | ||
readDir (str) { | ||
this.inFlight++; | ||
return fs.promises.readdir(str).then(list => { | ||
_.each(list, name => { | ||
let abs = path.resolve(str, name); | ||
let rel = path.relative(this.opts.root, abs); | ||
if (!this.exclude || !this.exclude(rel)) { | ||
this.pushToQueue(abs); | ||
} | ||
}); | ||
this.inFlight--; | ||
this.shouldRead = true; | ||
}); | ||
} | ||
createFile (str, stat) { | ||
return new this.constructor.File({ | ||
path: str, | ||
stat, | ||
cwd: this.opts.cwd, | ||
root: this.opts.root, | ||
encoding: this.opts.encoding | ||
}); | ||
} | ||
addFile (str, stat) { | ||
this.inFlight++; | ||
return new Promise((resolve, reject) => { | ||
let file = this.createFile(str, stat); | ||
if (!this.include || this.include(file.relative || file.base)) { | ||
this.push(file); | ||
this.shouldRead = false; | ||
} else { | ||
this.shouldRead = true; | ||
} | ||
this.inFlight--; | ||
resolve(); | ||
}); | ||
} | ||
walkFileOrDir (str) { | ||
this.pending++; | ||
return fs.promises.stat(str).then(stat => { | ||
this.pending--; | ||
if (stat.isDirectory()) { | ||
return this.readDir(str); | ||
} else { | ||
return this.addFile(str, stat); | ||
} | ||
}); | ||
} | ||
iterate (fn, res) { | ||
this.on('data', file => { | ||
while ((file = await this.resolver.next()) !== null) { | ||
if (fn) { | ||
try { | ||
file = fn(file); | ||
} catch (err) { | ||
this.destroy(err); | ||
} | ||
file = await fn(file); | ||
} | ||
@@ -305,12 +59,5 @@ if (res) { | ||
} | ||
}); | ||
} | ||
return new Promise((resolve, reject) => { | ||
this.once('end', () => { | ||
resolve(res); | ||
}); | ||
this.once('error', err => { | ||
reject(err); | ||
}); | ||
}); | ||
return res; | ||
@@ -320,12 +67,14 @@ } | ||
map (fn) { | ||
fn = _.isFunction(fn) ? fn : file => file; | ||
return this.iterate(fn, []); | ||
return this.iterate(_.isFunction(fn) ? fn : file => file, []); | ||
} | ||
tap (fn) { | ||
return this.iterate(_.isFunction(fn) ? async file => { await fn(file); return file; } : file => file, []); | ||
} | ||
each (fn) { | ||
fn = _.isFunction(fn) ? fn : _.noop; | ||
return this.iterate(fn); | ||
return this.iterate(_.isFunction(fn) ? fn : _.noop); | ||
} | ||
promise () { | ||
async promise () { | ||
return this.iterate(null, []); | ||
@@ -349,14 +98,14 @@ } | ||
static get WalkError () { | ||
return util.WalkError; | ||
} | ||
static get NotFoundError () { | ||
return NotFoundError; | ||
return util.NotFoundError; | ||
} | ||
static get NotResolvedError () { | ||
return NotResolvedError; | ||
return util.NotResolvedError; | ||
} | ||
static get constants () { | ||
return constants; | ||
} | ||
static get File () { | ||
@@ -366,4 +115,8 @@ return File; | ||
static get FileResolver () { | ||
return FileResolver; | ||
} | ||
} | ||
module.exports = Walk; |
{ | ||
"name": "@danmasta/walk", | ||
"version": "4.1.0", | ||
"version": "4.2.0", | ||
"author": "Daniel Smith <dannmasta@gmail.com>", | ||
@@ -16,5 +16,18 @@ "description": "Directory and file walking utility for node apps", | ||
"index.js", | ||
"sync.js", | ||
"lib/**/*" | ||
"index.mjs", | ||
"lib/**/*", | ||
"sync/**/*" | ||
], | ||
"exports": { | ||
".": { | ||
"import": "./index.mjs", | ||
"require": "./index.js" | ||
}, | ||
"./sync": { | ||
"import": "./sync/index.mjs", | ||
"require": "./sync/index.js" | ||
}, | ||
"./lib/*": "./lib/*.js", | ||
"./sync/*": "./sync/*.js" | ||
}, | ||
"scripts": { | ||
@@ -21,0 +34,0 @@ "test": "./node_modules/.bin/mocha tests", |
@@ -29,3 +29,3 @@ # Walk | ||
``` | ||
*By default walk returns a readable stream interface. You can use the methods: `map()`, `each()`, `promise()`, `then()`, and `catch()` to iterate file objects and return promises* | ||
*By default walk returns a readable stream interface. You can use the methods: `map()`, `tap()`, `each()`, `promise()`, `then()`, and `catch()` to iterate file objects and return promises* | ||
@@ -42,2 +42,3 @@ ### Options | ||
`resolve` | *`boolean`* | Whether or not to attempt to resolve file paths if not found. Default is `true` | ||
`paths` | *`array\|string`* | Which paths to walk for files. Default is `undefined` | ||
@@ -47,3 +48,4 @@ ### Methods | ||
-----|------------ | ||
`map(fn)` | Runs an iterator function over each file. Returns a promise that resolves with a new `array` | ||
`map(fn)` | Runs an iterator function over each file. Returns a promise that resolves with a new `array` of return values | ||
`tap(fn)` | Runs an iterator function over each file. Returns a promise that resolves with an `array` of file objects | ||
`each(fn)` | Runs an iterator function over each file. Returns a promise that resolves with `undefined` | ||
@@ -85,8 +87,13 @@ `promise` | Returns a promise that resolves with an `array` of file objects | ||
`require` | Reads the file contents using `require` | ||
`import` | Reads the file contents using `import`. Returns a promise | ||
`requireOrImport` | Reads the file contents using `import` or `require` based on esm-ness. Returns a promise | ||
`requireImportOrRead` | Reads the file contents using `import` or `require` if able, otherwise reads as string or buffer based on encoding. Returns a promise | ||
`isModule` | Returns `true` if `file.contents` is a [`module`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#module_namespace_object) | ||
`isBuffer` | Returns `true` if `file.contents` is a [`buffer`](https://nodejs.org/api/buffer.html#buffer_class_method_buffer_isbuffer_obj) | ||
`isStream` | Returns `true` if `file.contents` is a [`stream`](https://nodejs.org/api/stream.html) | ||
`isNull` | Returns `true` if `file.contents` is `null` | ||
`isNil` | Returns `true` if `file.contents` is `null` or `undefined` | ||
`isString` | Returns `true` if `file.contents` is a `string` | ||
`isDirectory` | Returns `true` if the file is a [directory](https://nodejs.org/api/fs.html#fs_stats_isdirectory) | ||
`isSymbolic` | Returns `true` if the file is a [symbolic link](https://nodejs.org/api/fs.html#fs_stats_issymboliclink) | ||
`isSymbolicLink` | 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) | ||
@@ -93,0 +100,0 @@ `isCharacterDevice` | Returns `true` if the file is a [character device](https://nodejs.org/api/fs.html#fs_stats_ischaracterdevice) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
34290
15
800
174
9
1