import * as fs from '@std/fs'; import * as path from '@std/path'; export type WALK_OPTIONS = { max_depth?: number; depth?: number; index?: number; filter?: (entry: WALK_ENTRY) => boolean; sort?: (a: WALK_ENTRY, b: WALK_ENTRY) => number; }; export type WALK_ENTRY = { path: string; info: Deno.FileInfo; depth: number; load: () => T; }; export async function* walk( root: string | URL, { depth = 0, filter = undefined, sort = undefined }: WALK_OPTIONS = {} ): AsyncIterableIterator> { const root_path = typeof root === 'string' ? path.resolve(root) : path.resolve(path.fromFileUrl(root)); const entries: WALK_ENTRY[] = []; const exists: boolean = await fs.exists(root_path); if (!exists) { return entries; } const root_info: Deno.FileInfo = await Deno.lstat(root_path); if (!root_info.isDirectory) { const entry: WALK_ENTRY = { path: root_path, info: root_info, depth, load: function () { return JSON.parse(Deno.readTextFileSync(this.path)) as T; } }; entries.push(entry); } else { for await (const dir_entry of Deno.readDir(root_path)) { const full_path = path.join(root, dir_entry.name); const info = await Deno.lstat(full_path); const entry = { path: full_path, info, depth, load: function () { return JSON.parse(Deno.readTextFileSync(this.path)) as T; } }; entries.push(entry); } } if (sort) { entries.sort(sort); } for (const entry of entries) { if (!filter || filter(entry)) { yield entry; } if (entry.info.isDirectory) { yield* walk(entry.path, { depth: depth + 1, filter, sort }); } } }