Skip to content

Importing modules by folder throws EISDIR #18

@bryan-hoang

Description

@bryan-hoang

VS Code supports resolving import("./folder") style typedefs in JSDoc comments, but the plugin assumes that the basename of the path will be a file rather than a folder.

A minimal repro of the error:

echo '{}' > package.json
npm add --save-dev jsdoc jsdoc-tsimport-plugin
npm pkg set scripts.jsdoc='jsdoc -c jsdoc.config.json index.js'
echo '{ "plugins": ["node_modules/jsdoc-tsimport-plugin/index.js"] }' > jsdoc.config.json
echo '/** @typedef {import("./src").foo} foo */' > index.js
mkdir src
cat > src/index.js <<EOL
/** @typedef {string} foo */
module.exports = {};
EOL
npm run jsdoc

The key part being import("./src") instead of import("./src/index") or import("./src/index.js").

Error output
Error: EISDIR: illegal operation on a directory, read
    at Object.readSync (node:fs:772:3)
    at tryReadSync (node:fs:441:20)
    at Object.readFileSync (node:fs:495:19)
    at getFileInfo (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:82:6)
    at getModuleId (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:159:10)
    at /home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:138:26
    at String.replace (<anonymous>)
    at /home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:136:24
    at String.replace (<anonymous>)
    at Parser.beforeParse (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc-tsimport-plugin/index.js:134:23)
    at Parser.emit (node:events:514:28)
    at Parser._parseSourceCode (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/lib/jsdoc/src/parser.js:288:18)
    at Parser.parse (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/lib/jsdoc/src/parser.js:202:22)
    at module.exports.cli.parseFiles (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/cli.js:365:46)
    at module.exports.cli.main (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/cli.js:234:18)
    at module.exports.cli.runCommand (/home/bryan/src/localhost/jsdoc-app/node_modules/jsdoc/cli.js:186:9) {
  errno: -21,
  syscall: 'read',
  code: 'EISDIR'
}
Suggestion for a potential fix
diff --git i/index.js w/index.js
index 4d8309e..7731951 100644
--- i/index.js
+++ w/index.js
@@ -160,7 +160,7 @@ function getModuleId(filename, relImportPath) {
   }

   const p = relPath(filename, relImportPath);
-  const absPath = inferExtension(p);
+  const absPath = require.resolve(p);
   return getFileInfo(absPath).moduleId;
 }

@@ -177,30 +177,6 @@ function relPath(root, relative) {
     path.join(path.dirname(root), relative));
 }

-/**
- * Given a filename, if there is no extension, scan the files for the
- * most likely match.
- *
- * @param {string} filename The filename with or without an
- * extension to resolve.
- * @returns {string} The path to the resolved file.
- */
-function inferExtension(filename) {
-  const filenameNor = path.normalize(filename);
-  const ext = path.extname(filenameNor);
-  if (ext && fs.existsSync(filename)) return ext;
-  const files = fs.readdirSync(path.dirname(filenameNor));
-
-  const name = path.basename(filenameNor);
-  const foundFile = files.find((iFile) => {
-    if (noExtension(iFile) == name) {
-      return true;
-    }
-  });
-  if (foundFile === undefined) return filename;
-  return path.join(path.dirname(filenameNor), foundFile);
-}
-
 /**
  * Strips the extension off of a filename.
  *

Replacing inferExtension with require.resolve to use the built-in module system to figure out the file being required could be a way to get around having to re-implement the module file resolution algorithm that VS Code uses. It works with CJS modules, but I haven't tried it with ES modules.

I could live with switching to importing ./src/index, but it'll be annoying having to inform teammates about this restriction in the future when it looks fine for them in VS Code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions