unjs/unimport

Error: EISDIR: illegal operation on a directory, read

Closed this issue · 3 comments

Environment

Cloned repository on Windows 10 22H2 running Node v16.17.0

Reproduction

Change playground/composables/nested/index.ts to

export default function () {
  return 'from nested composables'
}

+ export * from './bar'

Describe the bug

export async function scanExports (filepath: string, seen = new Set<string>()): Promise<Import[]> {
if (seen.has(filepath)) {
// eslint-disable-next-line no-console
console.warn(`[unimport] "${filepath}" is already scanned, skipping`)
return []
}
seen.add(filepath)
const imports: Import[] = []
const code = await readFile(filepath, 'utf-8')

scanExports is likely to assume that filepath is indeed a filepath while it can be a directory, and so readFile fails for the above example where the filepath is playground/composables/nested/bar (with no file extension lookup available for it).

Additional context

Options I can think of:

  1. Check if equivalent /index exists.

if (existsSync(`${subfilepath}${ext}`)) {
subfilepath = `${subfilepath}${ext}`
break
}

if (existsSync(`${subfilepath}${ext}`)) {
  subfilepath = `${subfilepath}${ext}`
  break
+} else if (existsSync(`${subfilepath}/index${ext}`)) {
+  // 'foo' is a directory
+  subfilepath = `${subfilepath}/index${ext}`
+  break
+}
  1. I also believed that recursion wouldn't be required, but rather forward the imports. #216 (comment)

imports.push(...await scanExports(subfilepath, seen))

- imports.push(...await scanExports(subfilepath, seen))
+ imports.push({ name: '*', from: subfilepath })

Logs

No response

antfu commented

Nice found, PR welcome!

Thanks! Would you recommend option 2? (could be more efficient)

Edit: it probably won't do - name is necessary so far

antfu commented

We need option 1, exporting * won't help as we need to know all the export name