83

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

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Ayoub k
  • 7,788
  • 9
  • 34
  • 57
  • 4
    when using type module you have to do it like: `import database from './database.js'` don't forget .js – webcoder Oct 20 '20 at 22:01
  • Do you mean `'database/index.js'`? it doesn't work. – Ayoub k Oct 20 '20 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` – webcoder Oct 20 '20 at 22:14
  • @webcoder database.js doesn't exist so that doesn't make sense. – AlxVallejo Oct 22 '22 at 17:52

7 Answers7

75

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

import database from "./database/index.js"
php_nub_qq
  • 15,199
  • 21
  • 74
  • 144
  • 23
    The import can be kept as in the OP, if the [`--experimental-specifier-resolution=node` flag](https://stackoverflow.com/a/65588027/1269037) is passed. – Dan Dascalescu Jan 05 '21 at 23:30
  • 3
    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. – Jason Kohles Feb 24 '23 at 20:00
  • 1
    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 Apr 17 '23 at 16:29
  • @jcalfee314 I honestly don't see this as an issue, all you need is an IDE that can resolve imports for you. – php_nub_qq Apr 18 '23 at 11:53
  • Can typescript automatically convert directory imports? – Simon Tran Jun 05 '23 at 14:42
  • see also `resolveFullPaths` of [ts-alias](https://www.npmjs.com/package/tsc-alias) – milahu Aug 11 '23 at 07:29
45

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.

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
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.

blue pine
  • 472
  • 6
  • 17
0

According to nodejs documentation, directory imports doesn't work

0

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: "kishandobariyadk7301@gmail.com",
  },
  gender: {
    type: DataTypes.STRING,
  },
},
{
  // timestamps: false,
  // updatedAt: false,
  // createdAt: false,
  // createdAt: created_at,
  // updatedAt: modified_at,
  // engine: "Kishan",
}
`);
};


export default Users;
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"
}
Yulian
  • 6,262
  • 10
  • 65
  • 92
-3

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.

benomatis
  • 5,536
  • 7
  • 36
  • 59
TValidator
  • 39
  • 1
  • 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 – Ayoub k Oct 20 '20 at 22:06
  • 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. – TValidator Oct 29 '20 at 19:38
  • 1
    it's not me who gave the negative vote. sorry about that. – Ayoub k Nov 01 '20 at 15:51
  • Sorry. I was not aware. – TValidator Nov 02 '20 at 11:32
  • I don't have much knowledge about point system in Stack Overflow but I'm very much sure you gave me some points. Thank you so much for that. Normally I don't perticipate anywhere. Recently I lauched one of my product 'TValidator' and trying to market in organic way. That is the reasson why I started participating in this platform but suddenly I was blocked by admin for -2 points. Sorry for my rude behavior and Thanks again. – TValidator Nov 03 '20 at 19:40
  • 1
    Babel is a stopgap solution. So are [Node flags](https://stackoverflow.com/a/65588027/1269037), but they're far lighter and faster. – Dan Dascalescu Jan 05 '21 at 23:28
  • TValidator, you must make babel.config.json file. I vote your answer to up, now 0 ^-^ – blue pine Jun 03 '21 at 15:30