(page: 0, pageSize = 40, searchFileName?: string)
| 117 | } |
| 118 | |
| 119 | async list(page: 0, pageSize = 40, searchFileName?: string) { |
| 120 | if (pageSize > 100 || pageSize <= 0 || page < 0) throw new Error("Beyond the value limit"); |
| 121 | |
| 122 | this.assertInsideWorkspace("."); |
| 123 | |
| 124 | // Use withFileTypes option to get file type directly, reducing stat calls |
| 125 | const dirents = await fs.readdir(this.toAbsolutePath(), { withFileTypes: true }); |
| 126 | |
| 127 | // Filter search results and create basic file info with type |
| 128 | let filteredItems = await Promise.all( |
| 129 | dirents |
| 130 | .filter( |
| 131 | (dirent) => |
| 132 | !searchFileName || dirent.name.toLowerCase().includes(searchFileName.toLowerCase()) |
| 133 | ) |
| 134 | .map(async (dirent) => { |
| 135 | let type = dirent.isFile() ? 1 : 0; |
| 136 | if (type === 0 && !dirent.isDirectory()) { |
| 137 | // Symbolic links may return false for both isFile() and isDirectory() |
| 138 | // see #2124 |
| 139 | try { |
| 140 | type = (await fs.stat(this.toAbsolutePath(dirent.name))).isFile() ? 1 : 0; |
| 141 | } catch {} |
| 142 | } |
| 143 | return { name: dirent.name, type }; |
| 144 | }) |
| 145 | ); |
| 146 | |
| 147 | const total = filteredItems.length; |
| 148 | |
| 149 | // Sort: directories first (type 0), then files (type 1), both alphabetically |
| 150 | filteredItems.sort((a, b) => { |
| 151 | if (a.type !== b.type) return a.type - b.type; |
| 152 | return a.name.localeCompare(b.name); |
| 153 | }); |
| 154 | |
| 155 | const sliceStart = page * pageSize; |
| 156 | const sliceEnd = sliceStart + pageSize; |
| 157 | const targetItems = filteredItems.slice(sliceStart, sliceEnd); |
| 158 | |
| 159 | const statPromises = targetItems.map(async (item) => { |
| 160 | try { |
| 161 | const info = await fs.stat(this.toAbsolutePath(item.name)); |
| 162 | const mode = parseInt(String(parseInt(info.mode?.toString(8), 10)).slice(-3)); |
| 163 | return { |
| 164 | name: item.name, |
| 165 | size: info.isFile() ? info.size : 0, |
| 166 | time: info.atime.toString(), |
| 167 | mode, |
| 168 | type: item.type |
| 169 | }; |
| 170 | } catch (error: any) { |
| 171 | return { |
| 172 | name: item.name, |
| 173 | size: 0, |
| 174 | time: new Date().toString(), |
| 175 | mode: 0, |
| 176 | type: item.type |
nothing calls this directly
no test coverage detected