+42
-55
| 'use strict'; | ||
| const fs = require('fs'); | ||
| const {Readable} = require('stream'); | ||
| const { Readable } = require('stream'); | ||
| const sysPath = require('path'); | ||
| const picomatch = require('picomatch'); | ||
| const {promisify} = require('util'); | ||
| const { promisify } = require('util'); | ||
| const [readdir, stat, lstat] = [promisify(fs.readdir), promisify(fs.stat), promisify(fs.lstat)]; | ||
@@ -33,5 +33,7 @@ const supportsDirent = 'Dirent' in fs; | ||
| const isNormalFlowError = (errorCode) => NORMAL_FLOW_ERRORS.has(errorCode); | ||
| const isNormalFlowError = errorCode => NORMAL_FLOW_ERRORS.has(errorCode); | ||
| const normalizeFilter = (filter) => { | ||
| const checkBasename = f => f(entry.basename); | ||
| const normalizeFilter = filter => { | ||
| if (filter === undefined) return; | ||
@@ -42,3 +44,3 @@ if (typeof filter === 'function') return filter; | ||
| const glob = picomatch(filter.trim()); | ||
| return (entry) => glob(entry.basename); | ||
| return entry => glob(entry.basename); | ||
| } | ||
@@ -60,9 +62,9 @@ | ||
| if (positive.length > 0) { | ||
| return (entry) => positive.some(f => f(entry.basename)) && | ||
| !negative.some(f => f(entry.basename)); | ||
| return entry => | ||
| positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename)); | ||
| } else { | ||
| return (entry) => !negative.some(f => f(entry.basename)); | ||
| return entry => !negative.some(f => f(entry.basename)); | ||
| } | ||
| } else { | ||
| return (entry) => positive.some(f => f(entry.basename)); | ||
| return entry => positive.some(f => f(entry.basename)); | ||
| } | ||
@@ -83,4 +85,4 @@ } | ||
| root: '.', | ||
| fileFilter: (path) => true, | ||
| directoryFilter: (path) => true, | ||
| fileFilter: path => true, | ||
| directoryFilter: path => true, | ||
| type: 'files', | ||
@@ -90,9 +92,9 @@ lstat: false, | ||
| alwaysStat: false | ||
| } | ||
| }; | ||
| } | ||
| constructor(options = {}) { | ||
| super({objectMode: true, highWaterMark: 1}); | ||
| super({ objectMode: true, highWaterMark: 1, autoDestroy: true }); | ||
| const opts = Object.assign({}, ReaddirpStream.defaultOptions, options); | ||
| const {root} = opts; | ||
| const { root } = opts; | ||
@@ -102,9 +104,9 @@ this._fileFilter = normalizeFilter(opts.fileFilter); | ||
| this._statMethod = opts.lstat ? lstat : stat; | ||
| this._statOpts = {bigint: isWindows}; | ||
| this._statOpts = { bigint: isWindows }; | ||
| this._maxDepth = opts.depth; | ||
| this._entryType = opts.type | ||
| this._root = root; | ||
| this._entryType = opts.type; | ||
| this._root = sysPath.resolve(root); | ||
| this._isDirent = !opts.alwaysStat && supportsDirent; | ||
| this._statsProp = this._isDirent ? 'dirent' : 'stats'; | ||
| this._readdir_options = {encoding: 'utf8', withFileTypes: this._isDirent}; | ||
| this._readdir_options = { encoding: 'utf8', withFileTypes: this._isDirent }; | ||
@@ -118,6 +120,6 @@ // Launch stream with one parent, the root dir. | ||
| async _read() { | ||
| // If the stream was destroyed, we must not proceed. | ||
| if (!this.readable) return; | ||
| do { | ||
| // If the stream was destroyed, we must not proceed. | ||
| if (this.destroyed) return; | ||
| do { | ||
| const parent = this.parents.pop(); | ||
@@ -131,3 +133,3 @@ if (!parent) { | ||
| await this._exploreDirectory(parent); | ||
| } while(!this.isPaused() && !this._isQueueEmpty()); | ||
| } while (!this.isPaused() && !this._isQueueEmpty()); | ||
@@ -155,9 +157,9 @@ this._endStreamIfQueueIsEmpty(); | ||
| // If the stream was destroyed, after readdir is completed | ||
| if (!this.readable) return; | ||
| if (this.destroyed) return; | ||
| this.filesToRead += files.length; | ||
| const entries = await Promise.all(files.map(dirent => this._formatEntry(dirent, parent))); | ||
| const entries = await Promise.all(files.map(dirent => this._formatEntry(dirent, parent))); | ||
| if (!this.readable) return; | ||
| if (this.destroyed) return; | ||
@@ -180,3 +182,3 @@ for (let i = 0; i < entries.length; i++) { | ||
| _isStatOptionsSupported() { | ||
| return this._statMethod.length === STAT_OPTIONS_SUPPORT_LENGTH; | ||
| return this._statMethod.length === STAT_OPTIONS_SUPPORT_LENGTH; | ||
| } | ||
@@ -193,4 +195,4 @@ | ||
| async _formatEntry(dirent, parent) { | ||
| const relativePath = this._isDirent ? dirent.name : dirent; | ||
| const fullPath = sysPath.resolve(sysPath.join(parent.path, relativePath)); | ||
| const basename = this._isDirent ? dirent.name : dirent; | ||
| const fullPath = sysPath.resolve(sysPath.join(parent.path, basename)); | ||
@@ -213,6 +215,5 @@ let stats; | ||
| const path = sysPath.relative(this._root, fullPath); | ||
| const basename = sysPath.basename(path); | ||
| /** @type {EntryInfo} */ | ||
| const entry = {path, fullPath, basename, [this._statsProp]: stats}; | ||
| const entry = { path, fullPath, basename, [this._statsProp]: stats }; | ||
@@ -235,3 +236,3 @@ return entry; | ||
| this.parents.push(new ExploringDir(parentPath, depth)); | ||
| return true | ||
| return true; | ||
| } else { | ||
@@ -248,6 +249,5 @@ return false; | ||
| const stats = entry[this._statsProp]; | ||
| const isFileType = ( | ||
| const isFileType = | ||
| (this._entryType === EVERYTHING_TYPE && !stats.isDirectory()) || | ||
| (stats.isFile() || stats.isSymbolicLink()) | ||
| ); | ||
| (stats.isFile() || stats.isSymbolicLink()); | ||
| return isFileType && this._fileFilter(entry); | ||
@@ -259,3 +259,5 @@ } | ||
| // TODO: Understand why this happens. | ||
| const fn = () => {this._push(entry)}; | ||
| const fn = () => { | ||
| this.push(entry); | ||
| }; | ||
| if (this._isDirent) setImmediate(fn); | ||
@@ -268,8 +270,2 @@ else fn(); | ||
| if (FILE_TYPES.has(this._entryType)) { | ||
| this._push(entry); | ||
| } | ||
| } | ||
| _push(entry) { | ||
| if (this.readable) { | ||
| this.push(entry); | ||
@@ -280,19 +276,10 @@ } | ||
| _handleError(error) { | ||
| if (!this.readable) { | ||
| return; | ||
| if (!this.destroyed) { | ||
| this.emit('warn', error); | ||
| } | ||
| this.emit('warn', error); | ||
| } | ||
| _handleFatalError(error) { | ||
| if (!this.readable) { | ||
| return; | ||
| } | ||
| this.emit('error', error); | ||
| this.destroy(); | ||
| this.destroy(error); | ||
| } | ||
| destroy() { | ||
| this.emit('close'); | ||
| } | ||
| } | ||
@@ -336,5 +323,5 @@ | ||
| readdirp(root, options) | ||
| .on('data', (entry) => files.push(entry)) | ||
| .on('data', entry => files.push(entry)) | ||
| .on('end', () => resolve(files)) | ||
| .on('error', (error) => reject(error)); | ||
| .on('error', error => reject(error)); | ||
| }); | ||
@@ -341,0 +328,0 @@ }; |
+1
-1
| { | ||
| "name": "readdirp", | ||
| "description": "Recursive version of fs.readdir with streaming api.", | ||
| "version": "3.1.3", | ||
| "version": "3.2.0", | ||
| "homepage": "https://github.com/paulmillr/readdirp", | ||
@@ -6,0 +6,0 @@ "repository": { |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
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
18844
-0.87%306
-3.77%