From 426f9e102bf7664879a4d34f93df78b6bc3ca6b8 Mon Sep 17 00:00:00 2001 From: James Bronder <36022278+jbronder@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:01:12 -0800 Subject: [PATCH 1/4] docs: update `readDir` docs with `param` and `returns` --- fs/unstable_read_dir.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/unstable_read_dir.ts b/fs/unstable_read_dir.ts index f41b05f44d93..d34fc520a2d5 100644 --- a/fs/unstable_read_dir.ts +++ b/fs/unstable_read_dir.ts @@ -5,9 +5,14 @@ import { mapError } from "./_map_error.ts"; import { toDirEntry } from "./_to_dir_entry.ts"; import type { DirEntry } from "./unstable_types.ts"; -/** Reads the directory given by `path` and returns an async iterable of +/** + * Reads the directory given by `path` and returns an async iterable of * {@linkcode DirEntry}. The order of entries is not guaranteed. * + * Throws Error if `path` is not a directory. + * + * Requires `allow-read` permission. + * * @example Usage * ```ts * import { readDir } from "@std/fs/unstable-read-dir"; @@ -17,12 +22,10 @@ import type { DirEntry } from "./unstable_types.ts"; * } * ``` * - * Throws error if `path` is not a directory. - * - * Requires `allow-read` permission. - * * @tags allow-read - * @category File System + * + * @param path The path to the directory. + * @returns An async iterable of `DirEntry` elements. */ export async function* readDir(path: string | URL): AsyncIterable { if (isDeno) { From 33d348dd8395f53e2a6927733fc7028632dff404 Mon Sep 17 00:00:00 2001 From: James Bronder <36022278+jbronder@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:04:12 -0800 Subject: [PATCH 2/4] feat(fs/unstable): add `readDirSync` function --- fs/unstable_read_dir.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/fs/unstable_read_dir.ts b/fs/unstable_read_dir.ts index d34fc520a2d5..99fd7bb0ac48 100644 --- a/fs/unstable_read_dir.ts +++ b/fs/unstable_read_dir.ts @@ -41,3 +41,40 @@ export async function* readDir(path: string | URL): AsyncIterable { } } } + +/** + * Synchronously reads the directory given by `path` and returns an iterable + * of {@linkcode Deno.DirEntry}. The order of entries is not guaranteed. + * + * Throws Error if `path` is not a directory. + * + * Requires `allow-read` permission. + * + * @example Usage + * ```ts + * import { readDirSync } from "@std/fs/unstable-read-dir"; + * + * for (const dirEntry of readDirSync("/")) { + * console.log(dirEntry.name); + * } + * ``` + * + * @tags allow-read + * + * @param path The path to the directory. + * @returns An iterator object of `DirEntry` elements. + */ +export function* readDirSync(path: string | URL): IteratorObject { + if (isDeno) { + return yield* Deno.readDirSync(path); + } else { + try { + const dir = getNodeFs().readdirSync(path, { withFileTypes: true }); + for (const entry of dir) { + yield toDirEntry(entry); + } + } catch (error) { + throw mapError(error); + } + } +} From 462b683eca0b42c7671d09b6f577f23f42b06837 Mon Sep 17 00:00:00 2001 From: James Bronder <36022278+jbronder@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:36:53 -0800 Subject: [PATCH 3/4] style: fix format for NotFound `readDir` test --- fs/unstable_read_dir_test.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/fs/unstable_read_dir_test.ts b/fs/unstable_read_dir_test.ts index c955798989e5..35cfd2bbf860 100644 --- a/fs/unstable_read_dir_test.ts +++ b/fs/unstable_read_dir_test.ts @@ -32,10 +32,7 @@ Deno.test("readDir() rejects when the path is not a directory", async () => { }); Deno.test("readDir() rejects when the directory does not exist", async () => { - await assertRejects( - async () => { - await readDir("non_existent_dir")[Symbol.asyncIterator]().next(); - }, - NotFound, - ); + await assertRejects(async () => { + await readDir("non_existent_dir")[Symbol.asyncIterator]().next(); + }, NotFound); }); From 49c01ca4995821dcc5bee90c1a84d95a11ce142e Mon Sep 17 00:00:00 2001 From: James Bronder <36022278+jbronder@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:39:11 -0800 Subject: [PATCH 4/4] test: add `readDirSync` tests --- fs/unstable_read_dir_test.ts | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/fs/unstable_read_dir_test.ts b/fs/unstable_read_dir_test.ts index 35cfd2bbf860..0154081cf00b 100644 --- a/fs/unstable_read_dir_test.ts +++ b/fs/unstable_read_dir_test.ts @@ -1,8 +1,8 @@ // Copyright 2018-2025 the Deno authors. MIT license. -import { assert, assertEquals, assertRejects } from "@std/assert"; +import { assert, assertEquals, assertRejects, assertThrows } from "@std/assert"; import { fromFileUrl, join, resolve } from "@std/path"; -import { readDir } from "./unstable_read_dir.ts"; +import { readDir, readDirSync } from "./unstable_read_dir.ts"; import { NotFound } from "./unstable_errors.js"; const testdataDir = resolve(fromFileUrl(import.meta.url), "../testdata"); @@ -36,3 +36,33 @@ Deno.test("readDir() rejects when the directory does not exist", async () => { await readDir("non_existent_dir")[Symbol.asyncIterator]().next(); }, NotFound); }); + +Deno.test("readDirSync() reads from the directory and its subdirectories", () => { + const files = []; + for (const e of readDirSync(testdataDir)) { + files.push(e); + } + + let counter = 0; + for (const f of files) { + if (f.name === "walk") { + assert(f.isDirectory); + counter++; + } + } + + assertEquals(counter, 1); +}); + +Deno.test("readDirSync() throws with Error when the path is not a directory", () => { + assertThrows(() => { + const testFile = join(testdataDir, "0.ts"); + readDirSync(testFile)[Symbol.iterator]().next(); + }, Error); +}); + +Deno.test("readDirSync() throws with NotFound when a directory does not exist", () => { + assertThrows(() => { + readDirSync("non_existent_dir")[Symbol.iterator]().next(); + }, NotFound); +});