111

I'm using Node.js v14.13.0.

app.js file:

import database from './database'; database(); 

database/index.js file:

import mongoose from 'mongoose'; export default connect = async () => { try { await mongoose.connect('...', { }); } catch (error) {} }; 

In package.json I added "type": "module".

After running the app I get the following error:

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/Users/xx/Desktop/Projects/node-starter/src/database' is not supported resolving ES modules imported from /Users/xx/Desktop/Projects/node-starter/src/app.js

4
  • 4
    when using type module you have to do it like: import database from './database.js' don't forget .js Commented Oct 20, 2020 at 22:01
  • Do you mean 'database/index.js'? it doesn't work. Commented Oct 20, 2020 at 22:04
  • I mean when importing make sure you add .js at the end of import like import database from './database.js' or you can use ems module and in your package.json just do nodemon -r esm main.js Commented Oct 20, 2020 at 22:14
  • 1
    @webcoder database.js doesn't exist so that doesn't make sense. Commented Oct 22, 2022 at 17:52

7 Answers 7

100
+100

With ES6 modules you can not (yet?) import directories. Your import should look like this:

import database from "./database/index.js" 
Sign up to request clarification or add additional context in comments.

7 Comments

The import can be kept as in the OP, if the --experimental-specifier-resolution=node flag is passed.
Unfortunately not any more. --experimental-specifier-resolution was first available in Node.js v12, and last available in v18, as of Node v19 it no longer exists and you have to use a custom loader instead.
Bummer, this is one of many things they are breaking. So sad to see JavaScript in its prime but simple bad decisions like this really makes it a liability to use. It will be a while, but I see it coming, all good things have to come to an end.
@jcalfee314 I honestly don't see this as an issue, all you need is an IDE that can resolve imports for you.
see also resolveFullPaths of ts-alias
|
52

What happens here is that Node mandates using an extension in import statements and also states,

Directory indexes (e.g. './startup/index.js') must also be fully specified.

Your import database from './database'; statement doesn't specify the index.js. You can add index.js as suggested in another answer, but that approach doesn't look elegant in TypeScript projects, when you'd end up importing a .js file from a .ts one.

You can change this Node extension resolution behavior by passing the --experimental-specifier-resolution=node flag. This will work and will keep your code unchanged:

app.js

import database from './database'; database(); 

Run as: node --experimental-specifier-resolution=node app.js.

A Node developer admitted that the documentation wasn't that clear.

2 Comments

doesn't work for me and nodejs 20.9.0
--experimental-specifier-resolution=node was removed in node v19. You have to use a custom loader now.
1

TValidator's answer is somewhat right, you can use babel to resolve this issue.
However, you must install @babel/core, @babel/node, @babel/preset-env.
And, you must make babel.config.json like belows;

{ "presets": ["@babel/preset-env"] } 

You should stay babel.config.json in the root folder of your project.
Now, you don't have to set "type": "module" to the package.json.

1 Comment

this is right. solution described is true.
1

With ES6 modules you can not (yet?) import directories.

Here you can see I made this changes and it worked for me this are my two files below and I needed to write require to import user for it but in ES6 it doesn't support require so in my solution I created the export default of users and it comes with sequelize and datatypes values so now I created import of users above in index.js file so I can use those values without using require.

Also you have to add (.js) extension in the imported files path just like I did in index.js files second line.

Your import should look like this:

Index.js

import { DataTypes, Sequelize } from "sequelize"; **import Users from "./users.js";** const sequelize = new Sequelize("Users", "root", "", { host: "localhost", dialect: "mysql", pool: { max: 5, min: 0, idle: 10000 }, }); sequelize .authenticate() .then(() => { console.log("Connected !"); }) .catch((err) => { console.log("Error", err); }); const db = {}; db.sequelize = Sequelize; db.sequelize = sequelize; **db.users = Users(sequelize, DataTypes);** db.sequelize.sync().then(() => { console.log("YES Re-Sync !"); }); export default sequelize; 

Users.js

const Users = (sequelize, DataTypes) => { sequelize.define( "Users", { name: { type: DataTypes.STRING, }, email: { type: DataTypes.STRING, defaultValue: "[email protected]", }, gender: { type: DataTypes.STRING, }, }, { // timestamps: false, // updatedAt: false, // createdAt: false, // createdAt: created_at, // updatedAt: modified_at, // engine: "Kishan", } `); }; export default Users; 

Comments

0

If you're getting this error as a result of importing a third-party library, you might have to move your dependency from devDependencies to dependencies. This is certainly not something that fits all use cases but still might make sense in your specific context.

This is what solved my issue:

// Before "devDependencies": { "third-party-lib": "version" } // After "dependencies": { "third-party-lib": "version" } 

Comments

-1

According to nodejs documentation, directory imports doesn't work

1 Comment

That's correct, but not quite the whole story.
-1

You can use babel. I used following babel library in node project and every ES6 features work properly.

"devDependencies": { "babel-cli": "^6.26.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-preset-env": "^1.6.1" } 

Although it may be old version but you can use latest version.

7 Comments

I was using babel and of course, it was working, but I decided to remove it as a dependency because it doesn't bring much to the table. I can use all es6 without using babe. I added type: "module" in my package.json so it should work. Thanks for the suggestion anyway
You didn't mention you were using babel already. If I knew I never try to give any suggestion for your negative vote. Thanks for your negative vote.
it's not me who gave the negative vote. sorry about that.
Sorry. I was not aware.
Babel is a stopgap solution. So are Node flags, but they're far lighter and faster.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.