| 160 | * |
| 161 | */ |
| 162 | export class Finder implements AsyncIterable<string> { |
| 163 | #excludedFolders = new Set<string | RegExp>(['winsxs', 'syswow64', 'system32']); |
| 164 | #files = accumulator<string>().autoComplete(false); |
| 165 | files = this.#files.reiterable(); |
| 166 | |
| 167 | private match: (file: File) => Promise<boolean> | boolean; |
| 168 | private promises = new Array<Promise<void>>(); |
| 169 | |
| 170 | constructor(executableName: string); |
| 171 | constructor(executableRegEx: RegExp); |
| 172 | constructor(fileMatcher: (file: File) => Promise<boolean> | boolean); |
| 173 | constructor(binary: string | RegExp | ((file: File) => Promise<boolean> | boolean)) { |
| 174 | switch (typeof binary) { |
| 175 | case 'string': |
| 176 | this.match = (file: File) => file.isExecutable && file.basename === binary; |
| 177 | break; |
| 178 | case 'function': |
| 179 | this.match = binary; |
| 180 | break; |
| 181 | case 'object': |
| 182 | this.match = (file: File) => file.isExecutable && !!file.basename.match(binary); |
| 183 | break; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | static resetCache() { |
| 188 | cache.clear(); |
| 189 | } |
| 190 | |
| 191 | exclude(folder: string) { |
| 192 | this.#excludedFolders.add(folder); |
| 193 | } |
| 194 | |
| 195 | /** |
| 196 | * Add one or more locations to scan, with an optionally specified depth. |
| 197 | * |
| 198 | * The scanning of those locations begins immediately and is done asynchronously. |
| 199 | * |
| 200 | */ |
| 201 | scan(...location: (Promise<string> | string)[]): Finder; |
| 202 | scan(depth: number, ...location: (Promise<string> | string)[]): Finder; |
| 203 | scan(...location: (Promise<string> | string | number)[]): Finder { |
| 204 | const depth = typeof location[0] === 'number' ? location.shift() as number : 0; |
| 205 | this.promises.push(...location.map(each => scanFolder(each.toString(), depth, this.match, (f) => !this.#excludedFolders.has(f.name), this.#files))); |
| 206 | return this; |
| 207 | } |
| 208 | |
| 209 | [Symbol.asyncIterator](): AsyncIterator<string> { |
| 210 | this.#files.complete(); |
| 211 | return this.#files[Symbol.asyncIterator](); |
| 212 | } |
| 213 | |
| 214 | get results(): Promise<Set<string>> { |
| 215 | return Promise.all(this.promises).then(async () => { |
| 216 | const result = new Set<string>(); |
| 217 | for await (const file of this) { |
| 218 | result.add(file); |
| 219 | } |
nothing calls this directly
no test coverage detected