Reputation: 9519
I'm going through this tutorial on discord.js. When I ran the code as written, I got errors like SyntaxError: Cannot use import statement outside a module
.
So, I added "type": "module"
to package.json
I managed to get the early examples to run. Now, i'm working on a section of code:
import dotenv from "dotenv";
dotenv.config();
const token = process.env.DTOKEN;
// const fs = require('node:fs');
import fs from 'node:fs';
// const path = require('node:path');
import path from 'node:path';
// Require the necessary discord.js classes
import { Client, Collection, Intents } from "discord.js";
// const { token } = require('./config.json');
// Create a new client instance
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection
// With the key as the command name and the value as the exported module
client.commands.set(command.data.name, command);
}
// When the client is ready, run this code (only once)
client.once('ready', () => {
console.log('Ready!');
});
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const { commandName } = interaction;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
// Login to Discord with your client's token
client.login(token);
I'm getting: ReferenceError: __dirname is not defined in ES module scope
I don't see a lot to go on in SO. Questions like this one just put me back to square one.
What am I missing?
Upvotes: 42
Views: 35897
Reputation: 2282
For ESM projects I've been using import.meta.dirname
- which is the "directory name of the current module" - aka a string that is the absolute path to the current script's folder - https://nodejs.org/api/esm.html#importmetadirname
// FILE: src/server.js
import fs from "fs";
// log out absolute path to folder (src) that contains server.js
console.log(import.meta.dirname); // /Users/timmy/Desktop/node-stuff/proj/src
// location of index.html relative to this JS file
const indexPath = "/../client/index.html";
// concatenate them to get absolute path to index.html
const absolutePath = `${import.meta.dirname}${indexPath}`;
// load the file
const index = fs.readFileSync(absolutePath, "utf-8");
Upvotes: 4
Reputation: 35
There is a simpler solution appeared not long ago. Now you can install common-es npm package and use it like this:
import { getGlobals } from 'common-es'
const { __dirname, __filename } = getGlobals(import.meta.url)
// now you can use __dirname or file name normally as you would do in commonjs
// ...
Upvotes: 2
Reputation: 6270
__filename
and __dirname
are only available in CommonJS modules according to Nodejs documentation.
Use fileURLToPath(import.meta.url)
get file path of the current file/module. If you need containing directory path use path.dirname()
Upvotes: 8
Reputation: 9519
This article helps solve the issue: https://bobbyhadz.com/blog/javascript-dirname-is-not-defined-in-es-module-scope
Here's the code from the article:
import path from 'path';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
// 👇️ "/home/john/Desktop/javascript"
const __dirname = path.dirname(__filename);
console.log('directory-name 👉️', __dirname);
// 👇️ "/home/borislav/Desktop/javascript/dist/index.html"
console.log(path.join(__dirname, '/dist', 'index.html'));
Upvotes: 70