11// @ts -check
22
3+ /**
4+ * @typedef {import('fs').Stats } Stats
5+ */
6+
37'use strict'
48
59const fs = require ( 'fs' )
@@ -9,93 +13,108 @@ const ignore = require('ignore')
913const { readdir, lstat } = fs . promises
1014
1115/**
12- * pathFilter lets you filter files based on a resolved `filepath`.
13- * @callback pathFilter
14- * @param {String } filepath - The resolved `filepath` of the file to test for filtering.
16+ * PathFilter lets you filter files based on a resolved `filepath`.
17+ * @callback PathFilter
18+ * @param {string } filepath - The resolved `filepath` of the file to test for filtering.
1519 *
16- * @return {Boolean } Return false to filter the given `filepath` and true to include it.
20+ * @return {boolean } Return false to filter the given `filepath` and true to include it.
21+ */
22+
23+ /**
24+ * @type PathFilter
1725 */
18- const pathFilter = filepath => true
26+ const pathFilter = ( /* filepath */ ) => true
1927
2028/**
2129 * statFilter lets you filter files based on a lstat object.
22- * @callback statFilter
23- * @param {Object } st - A fs.Stats instance.
30+ * @callback StatFilter
31+ * @param {Stats } st - A fs.Stats instance.
2432 *
25- * @return {Boolean } Return false to filter the given `filepath` and true to include it.
33+ * @return {boolean } Return false to filter the given `filepath` and true to include it.
2634 */
27- const statFilter = st => true
35+
36+ /**
37+ * @type StatFilter
38+ */
39+ const statFilter = ( /* st */ ) => true
2840
2941/**
3042 * FWStats is the object that the okdistribute/folder-walker module returns by default.
3143 *
3244 * @typedef FWStats
33- * @property {String } root - The filepath of the directory where the walk started.
34- * @property {String } filepath - The resolved filepath .
35- * @property {Object } stat - A fs.Stats instance.
36- * @property {String } relname - The relative path to `root`.
37- * @property {String } basename - The resolved filepath of the files containing directory.
45+ * @property {string } root - The filepath of the directory where the walk started.
46+ * @property {string } filepath - The resolved assolute path .
47+ * @property {Stats } stat - A fs.Stats instance.
48+ * @property {string } relname - The relative path to `root`.
49+ * @property {string } basename - The resolved filepath of the files containing directory.
3850 */
3951
4052/**
41- * shaper lets you change the shape of the returned file data from walk-time stats.
42- * @callback shaper
53+ * Shaper lets you change the shape of the returned file data from walk-time stats.
54+ * @template T
55+ * @callback Shaper
4356 * @param {FWStats } fwStats - The same status object returned from folder-walker.
4457 *
45- * @return {* } - Whatever you want returned from the directory walk.
58+ * @return {T } - Whatever you want returned from the directory walk.
59+ */
60+
61+ /**
62+ * @type {Shaper<string> }
4663 */
47- const shaper = ( { root , filepath , stat, relname, basename } ) => filepath
64+ const shaper = ( { filepath /*, root , stat, relname, basename */ } ) => filepath
4865
4966/**
50- * Options object
67+ * Options object.
5168 *
52- * @typedef Opts
53- * @property {pathFilter } [pathFilter] - A pathFilter cb.
54- * @property {statFilter } [statFilter] - A statFilter cb.
55- * @property {String[] } [ignore] - An array of .gitignore style strings of files to ignore.
56- * @property {Number } [maxDepth=Infinity] - The maximum number of folders to walk down into.
57- * @property {shaper } [shaper] - A shaper cb.
69+ * @template T
70+ * @typedef {object } AFWOpts
71+ * @property {PathFilter } pathFilter=pathFilter - A pathFilter callback.
72+ * @property {StatFilter } statFilter=statFilter - A statFilter callback.
73+ * @property {string[] } ignore=[] - An array of .gitignore style strings of files to ignore.
74+ * @property {number } maxDepth=Infinity - The maximum number of folders to walk down into.
75+ * @property {Shaper<T> } shaper=shaper - A shaper callback.
5876 */
5977
6078/**
6179 * Create an async generator that iterates over all folders and directories inside of `dirs`.
6280 *
63- * @async
64- * @generator
65- * @function
81+ * @template T
6682 * @public
67- * @param {String|String[] } dirs - The path of the directory to walk, or an array of directory paths.
68- * @param {?(Opts) } opts - Options used for the directory walk.
69- *
70- * @yields {Promise<String|any>} - An async iterator that returns anything.
83+ * @param {string|string[] } dirs - The path or paths of the directory to walk.
84+ * @param {?Partial<AFWOpts<T>> } [opts] - Options used for the directory walk.
85+ * @yields {T} - An iterator that returns a value of type T.
7186 */
7287async function * asyncFolderWalker ( dirs , opts ) {
73- opts = Object . assign ( {
88+ /** @type {AFWOpts<T> } */
89+ const resolvedOpts = Object . assign ( {
7490 fs,
7591 pathFilter,
7692 statFilter,
77- ignore,
93+ ignore : [ ] ,
7894 maxDepth : Infinity ,
7995 shaper
8096 } , opts )
8197
8298 // @ts -ignore
83- const ig = ignore ( ) . add ( opts . ignore )
99+ const ig = ignore ( ) . add ( resolvedOpts . ignore )
84100
85- const roots = [ dirs ] . flat ( ) . filter ( opts . pathFilter )
101+ const roots = [ dirs ] . flat ( ) . filter ( resolvedOpts . pathFilter )
86102 const pending = [ ]
87103
88104 while ( roots . length ) {
89105 const root = roots . shift ( )
106+ if ( ! root ) continue // Handle potential undefined value
90107 pending . push ( root )
108+
91109 while ( pending . length ) {
92110 const current = pending . shift ( )
93- if ( typeof current === 'undefined' ) continue
111+ if ( ! current ) continue // Handle potential undefined value
112+
94113 const st = await lstat ( current )
95114 const rel = relname ( root , current )
96115 if ( ig . ignores ( st . isDirectory ( ) ? rel + '/' : rel ) ) continue
97- if ( ( ! st . isDirectory ( ) || depthLimiter ( current , root , opts . maxDepth ) ) && opts . statFilter ( st ) ) {
98- yield opts . shaper ( fwShape ( root , current , st ) )
116+ if ( ( ! st . isDirectory ( ) || depthLimiter ( current , root , resolvedOpts . maxDepth ) ) && resolvedOpts . statFilter ( st ) ) {
117+ yield resolvedOpts . shaper ( fwShape ( root , current , st ) )
99118 continue
100119 }
101120
@@ -104,32 +123,34 @@ async function * asyncFolderWalker (dirs, opts) {
104123
105124 for ( const file of files ) {
106125 const next = path . join ( current , file )
107- if ( opts . pathFilter ( next ) ) pending . unshift ( next )
126+ if ( resolvedOpts . pathFilter ( next ) ) pending . unshift ( next )
108127 }
109- if ( current === root || ! opts . statFilter ( st ) ) continue
110- else yield opts . shaper ( fwShape ( root , current , st ) )
128+ if ( current === root || ! resolvedOpts . statFilter ( st ) ) continue
129+ else yield resolvedOpts . shaper ( fwShape ( root , current , st ) )
111130 }
112131 }
113132}
114133
134+ /**
135+ * @param {string } root
136+ * @param {string } name
137+ * @return {string } The basename or relative name if root === name
138+ */
115139function relname ( root , name ) {
116140 return root === name ? path . basename ( name ) : path . relative ( root , name )
117141}
118142
119143/**
120144 * Generates the same shape as the folder-walker module.
121145 *
122- * @function
123- * @private
124- * @param {String } root - Root filepath.
125- * @param {String } name - Target filepath.
126- * @param {Object } st - fs.Stat object.
127- *
128- * @return {FWStats } - Folder walker object.
146+ * @param {string } root - Root filepath.
147+ * @param {string } name - Target filepath.
148+ * @param {Stats } st - fs.Stat object.
149+ * @returns {FWStats } Folder walker object.
129150 */
130151function fwShape ( root , name , st ) {
131152 return {
132- root : root ,
153+ root,
133154 filepath : name ,
134155 stat : st ,
135156 relname : relname ( root , name ) ,
@@ -140,13 +161,10 @@ function fwShape (root, name, st) {
140161/**
141162 * Test if we are at maximum directory depth.
142163 *
143- * @private
144- * @function
145- * @param {String } filePath - The resolved path of the target fille.
146- * @param {String } relativeTo - The root directory of the current walk.
147- * @param {Number } maxDepth - The maximum number of folders to descend into.
148- *
149- * @returns {Boolean } - Return true to signal stop descending.
164+ * @param {string } filePath - The resolved path of the target file.
165+ * @param {string } relativeTo - The root directory of the current walk.
166+ * @param {number } maxDepth - The maximum number of folders to descend into.
167+ * @returns {boolean } Return true to signal stop descending.
150168 */
151169function depthLimiter ( filePath , relativeTo , maxDepth ) {
152170 if ( maxDepth === Infinity ) return false
@@ -156,17 +174,16 @@ function depthLimiter (filePath, relativeTo, maxDepth) {
156174}
157175
158176/**
159- * Async iterable collector
177+ * Async iterable collector.
160178 *
161- * @async
162- * @function
163- * @private
164- * @param { AsyncIterator } iterator - The iterator to collect into an array
179+ * @template T
180+ * @public
181+ * @param { AsyncIterableIterator<T> } iterator - The iterator to collect into an array.
182+ * @returns { Promise<T[]> } Array of items collected from the iterator.
165183 */
166184async function all ( iterator ) {
167185 const collect = [ ]
168186
169- // @ts -ignore
170187 for await ( const result of iterator ) {
171188 collect . push ( result )
172189 }
@@ -175,15 +192,13 @@ async function all (iterator) {
175192}
176193
177194/**
178- * allFiles gives you all files from the directory walk as an array.
195+ * Gives you all files from the directory walk as an array.
179196 *
180- * @async
181- * @function
197+ * @template T
182198 * @public
183- * @param {String|String[] } dirs - The path of the directory to walk, or an array of directory paths.
184- * @param {?(Opts) } opts - Options used for the directory walk.
185- *
186- * @returns {Promise<String[]|any> } - An async iterator that returns anything.
199+ * @param {string|string[] } dirs - The path of the directory to walk, or an array of directory paths.
200+ * @param {Partial<AFWOpts<T>> } [opts] - Options used for the directory walk.
201+ * @returns {Promise<T[]> } Array of files or any other result from the directory walk.
187202 */
188203async function allFiles ( dirs , opts ) {
189204 return all ( asyncFolderWalker ( dirs , opts ) )
0 commit comments