11'use strict'
22
3+ const os = require ( 'node:os' )
34const path = require ( 'node:path' )
45const fs = require ( 'node:fs/promises' )
5- const pLimit = require ( 'p-limit' )
6+ const fastq = require ( 'fastq' )
7+ const fastqConcurrency = Math . max ( 1 , os . cpus ( ) . length - 1 )
68
79const dirList = {
10+ _getExtendedInfo : async function ( dir , info ) {
11+ const depth = dir . split ( path . sep ) . length
12+ const files = await fs . readdir ( dir )
13+
14+ const worker = async ( filename ) => {
15+ const filePath = path . join ( dir , filename )
16+ let stats
17+ try {
18+ stats = await fs . stat ( filePath )
19+ } catch {
20+ return
21+ }
22+
23+ if ( stats . isDirectory ( ) ) {
24+ info . totalFolderCount ++
25+ filePath . split ( path . sep ) . length === depth + 1 && info . folderCount ++
26+ await dirList . _getExtendedInfo ( filePath , info )
27+ } else {
28+ info . totalSize += stats . size
29+ info . totalFileCount ++
30+ filePath . split ( path . sep ) . length === depth + 1 && info . fileCount ++
31+ info . lastModified = Math . max ( info . lastModified , stats . mtimeMs )
32+ }
33+ }
34+ const queue = fastq . promise ( worker , fastqConcurrency )
35+ await Promise . all ( files . map ( filename => queue . push ( filename ) ) )
36+ } ,
37+
38+ /**
39+ * get extended info about a folder
40+ * @param {string } folderPath full path fs dir
41+ * @return {Promise<ExtendedInfo> }
42+ */
43+ getExtendedInfo : async function ( folderPath ) {
44+ const info = {
45+ totalSize : 0 ,
46+ fileCount : 0 ,
47+ totalFileCount : 0 ,
48+ folderCount : 0 ,
49+ totalFolderCount : 0 ,
50+ lastModified : 0
51+ }
52+
53+ await dirList . _getExtendedInfo ( folderPath , info )
54+
55+ return info
56+ } ,
57+
858 /**
959 * get files and dirs from dir, or error
1060 * @param {string } dir full path fs dir
@@ -22,8 +72,7 @@ const dirList = {
2272 return entries
2373 }
2474
25- const limit = pLimit ( 4 )
26- await Promise . all ( files . map ( filename => limit ( async ( ) => {
75+ const worker = async ( filename ) => {
2776 let stats
2877 try {
2978 stats = await fs . stat ( path . join ( dir , filename ) )
@@ -33,62 +82,15 @@ const dirList = {
3382 const entry = { name : filename , stats }
3483 if ( stats . isDirectory ( ) ) {
3584 if ( options . extendedFolderInfo ) {
36- entry . extendedInfo = await getExtendedInfo ( path . join ( dir , filename ) )
85+ entry . extendedInfo = await dirList . getExtendedInfo ( path . join ( dir , filename ) )
3786 }
3887 entries . dirs . push ( entry )
3988 } else {
4089 entries . files . push ( entry )
4190 }
42- } ) ) )
43-
44- async function getExtendedInfo ( folderPath ) {
45- const depth = folderPath . split ( path . sep ) . length
46- let totalSize = 0
47- let fileCount = 0
48- let totalFileCount = 0
49- let folderCount = 0
50- let totalFolderCount = 0
51- let lastModified = 0
52-
53- async function walk ( dir ) {
54- const files = await fs . readdir ( dir )
55- const limit = pLimit ( 4 )
56- await Promise . all ( files . map ( filename => limit ( async ( ) => {
57- const filePath = path . join ( dir , filename )
58- let stats
59- try {
60- stats = await fs . stat ( filePath )
61- } catch {
62- return
63- }
64-
65- if ( stats . isDirectory ( ) ) {
66- totalFolderCount ++
67- if ( filePath . split ( path . sep ) . length === depth + 1 ) {
68- folderCount ++
69- }
70- await walk ( filePath )
71- } else {
72- totalSize += stats . size
73- totalFileCount ++
74- if ( filePath . split ( path . sep ) . length === depth + 1 ) {
75- fileCount ++
76- }
77- lastModified = Math . max ( lastModified , stats . mtimeMs )
78- }
79- } ) ) )
80- }
81-
82- await walk ( folderPath )
83- return {
84- totalSize,
85- fileCount,
86- totalFileCount,
87- folderCount,
88- totalFolderCount,
89- lastModified
90- }
9191 }
92+ const queue = fastq . promise ( worker , fastqConcurrency )
93+ await Promise . all ( files . map ( filename => queue . push ( filename ) ) )
9294
9395 entries . dirs . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
9496 entries . files . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
@@ -115,6 +117,7 @@ const dirList = {
115117 } catch {
116118 return reply . callNotFound ( )
117119 }
120+
118121 const format = reply . request . query . format || options . format
119122 if ( format !== 'html' ) {
120123 if ( options . jsonFormat !== 'extended' ) {
@@ -203,7 +206,6 @@ const dirList = {
203206 return new TypeError ( 'The `list.render` option must be a function and is required with html format' )
204207 }
205208 }
206-
207209}
208210
209211module . exports = dirList
0 commit comments