Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curly-mirrors-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"debarrel": patch
---

Fix cloud runtime crash in project file walking when `readdirSync` entries lack a usable `.name` (avoid `entry.name.startsWith` on undefined).
56 changes: 48 additions & 8 deletions codemods/debarrel/scripts/utils/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,26 +337,66 @@ const MDX_FILE_PATTERN = /\.mdx$/;
const NAMESPACE_IMPORT_RE =
/import\s+\*\s+as\s+[\w$]+\s+from\s+['"]([^'"]+)['"]/g;

/** Recursively list source files under `rootDir`, skipping node_modules. */
/** Resolve a `readdirSync` entry to a file name across Node and curated fs. */
function readdirEntryName(entry: unknown): string | null {
if (typeof entry === "string") return entry;
if (
entry &&
typeof entry === "object" &&
"name" in entry &&
typeof (entry as { name: unknown }).name === "string"
) {
return (entry as { name: string }).name;
}
return null;
}

function readdirEntryIsDirectory(entry: unknown, fullPath: string): boolean {
if (
entry &&
typeof entry === "object" &&
typeof (entry as fs.Dirent).isDirectory === "function"
) {
try {
return (entry as fs.Dirent).isDirectory();
} catch {
// Fall through to stat.
}
}
try {
return fs.statSync(fullPath).isDirectory();
} catch {
return false;
}
}

/**
* Recursively list source files under `rootDir`, skipping node_modules.
*
* Uses plain `readdirSync` (string names) plus `statSync`. Cloud/LLRT curated
* fs has returned incomplete Dirents for `{ withFileTypes: true }`, which
* crashed on `entry.name.startsWith(...)`.
*/
export function walkProjectSourceFiles(
rootDir: string,
files: string[] = [],
): string[] {
const absoluteRoot = path.resolve(rootDir);
let entries: fs.Dirent[];
let entries: unknown[];
try {
entries = fs.readdirSync(absoluteRoot, { withFileTypes: true });
entries = fs.readdirSync(absoluteRoot);
} catch {
return files;
}
for (const entry of entries) {
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
const fullPath = path.resolve(absoluteRoot, entry.name);
if (entry.isDirectory()) {
const name = readdirEntryName(entry);
if (!name || name === "node_modules" || name.startsWith(".")) continue;
const fullPath = path.resolve(absoluteRoot, name);
if (readdirEntryIsDirectory(entry, fullPath)) {
walkProjectSourceFiles(fullPath, files);
} else if (
SOURCE_FILE_PATTERN.test(entry.name) ||
MDX_FILE_PATTERN.test(entry.name)
SOURCE_FILE_PATTERN.test(name) ||
MDX_FILE_PATTERN.test(name)
) {
files.push(fullPath);
}
Expand Down
Loading