#Convert require into import problem
136 messages · Page 1 of 1 (latest)
i Know that const {blabla} = require("discordjs") is converted to import {blabla} from "discordjs", but idk how to convert this code
import fun from <path>
fun(client) maybe
Idk if yoy can do one liners
import <path>(client) maybe but I doubt it
ok thanks
actually, I can't import. It's in a for loop:
const functionFolders = readdirSync("./src/functions");
for (const folder of functionFolders) {
const functionFiles = readdirSync(`./src/functions/${folder}`).filter(
(file) => file.endsWith(".js")
);
for (const file of functionFiles)
require(`./functions/${folder}/${file}`)(client);
}
ohh wait
const { default } = await import(<path>)
default(client)
Or similar, idk your setup
im getting this error:
TypeError: client.handleEvents is not a function
at file:///C:/Users/Waggerra/Documents/Discord/BOTS%20Discord/Tobor/src/index.js:28:8
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:113:12)
Node.js v20.11.1
I have this script:
import "dotenv/config";
const { TOKEN, databaseToken } = process.env;
import { connect } from "mongoose";
import { Client, Collection } from "discord.js";
import { readdirSync } from "fs";
const client = new Client({ intents: 32767 /* GatewayIntentBits.Guilds */ });
client.commands = new Collection();
client.buttons = new Collection();
client.selectMenus = new Collection();
client.modals = new Collection();
client.commandArray = [];
const functionFolders = readdirSync("./src/functions");
for (const folder of functionFolders) {
const functionFiles = readdirSync(`./src/functions/${folder}`).filter(
(file) => file.endsWith(".js")
);
for (const file of functionFiles) {
//require(`./functions/${folder}/${file}`)(client);
import(`./functions/${folder}/${file}`).then((module) => {
module.default(client);
});
}
}
client.handleEvents();
client.handleCommands();
client.handleComponents();
client.login(TOKEN);
(async () => {
await connect(databaseToken).catch(console.error);
})();
So it's an import problem.
it's a problem with the for (file of functionFiles) loop
Convert require into import problem
Show how you export that file
import "dotenv/config";
import { REST } from "@discordjs/rest";
import { Routes } from "discord-api-types/v9";
import { readdirSync } from "fs";
export default (client) => {
client.handleCommands = async () => {
const commandFolders = readdirSync("./src/commands");
for (const folder of commandFolders) {
const commandFiles = readdirSync(`./src/commands/${folder}`)
.filter((file) => file.endsWith(".js"));
const { commands, commandArray } = client;
for (const file of commandFiles) {
const command = require(`../../commands/${folder}/${file}`);
commands.set(command.data.name, command);
commandArray.push(command.data.toJSON());
console.log(
`Command: ${command.data.name} has passed through the handler.`
);
}
}
const clientId = "983040401747365888";
const guildId = "1107327478332145684";
const rest = new REST({ version: "9" }).setToken(process.env.TOKEN);
try {
console.log("Started refreshing application (/) commands.");
/*//*TEST / SINGLE SERVER
await rest.put(Routes.applicationGuildCommands(clientId, guildId), {
body: client.commandArray,
});*/
//!GLOBAL
await rest.put(Routes.applicationCommands(clientId), {
body: client.commandArray,
})
console.log("Successfully reloaded application (/) commands.");
} catch (error) {
console.log(error);
}
};
};
I converted all the files. It's just the index.js file that burn my balls 🔥 😡
import { readdirSync } from "fs";
export default (client) => {
BLABLA
};
@raw crane
Im trying to convert the code he writes at 11:40 into ESM
https://www.youtube.com/watch?v=6IgOXmQMT68&list=PLv0io0WjFNn9LDsv1W4fOWygNFzY342Jm
what did you end up with when trying to convert it?
So is this bit working then?
no It don't work.
Can you show the updated code and maybe log what the import returns with?
What I want, is to run client.handleEvents(). The problem is that it says "client.handleEvents" is not a function
import(...) is async, you need to await it
They use .then
yeah but it seems like the rest of the code depends on what happens in the .then
so maybe try moving the rest of the code in the .then
or use await
const functionFolders = readdirSync("./src/functions");
for (const folder of functionFolders) {
const functionFiles = readdirSync(`./src/functions/${folder}`).filter(
(file) => file.endsWith(".js")
);
for (const file of functionFiles) {
//require(`./functions/${folder}/${file}`)(client);
await import(`./functions/${folder}/${file}`)
.then(module => {
module.default(client);
});
}
}
//import {handleEvents} from "./functions/handlers/handleEvents";
client.handleEvents();
client.handleCommands();
client.handleComponents();
client.login(TOKEN);
I also get this error:
import { connection } from "mongoose";
That’s not an error
SyntaxError: Named export 'connection' not found. The requested module 'mongoose' is a CommonJS module, which may not support all module.exports as named exports.
man, I have to switch to ESM, and now I have to use CommonJS. What the hell is doing discordjs ?
discordjs is fine, it’s everything else
What is the client.handleEvents function
import { readdirSync } from "fs";
import { connection } from "mongoose";
export default client => {
client.handleEvents = async () => {
const eventFolders = readdirSync("./src/events");
for (const folder of eventFolders) {
const eventFiles = readdirSync(`./src/events/${folder}`)
.filter((file) => file.endsWith(".js"));
switch (folder) {
case "client":
for (const file of eventFiles) {
const event = require(`../../events/${folder}/${file}`);
if (event.once)
client.once(event.name, (...args) =>
event.execute(...args, client)
);
else
client.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
case "mongo":
for (const file of eventFiles) {
const event = require(`../../events/${folder}/${file}`);
if (event.once)
connection.once(event.name, (...args) =>
event.execute(...args, client)
);
else
connection.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
default:
break;
}
}
};
};
Honestly I ain’t too sure. I’m not very very familiar with import export syntax so you’ll have to wait for someone else
no problem
this kind of mutation is awkward
?
the thing is that I have like a double problem. One with the mongodb support and one with the import / export problem
uhhh I don't understand
how do other devs do ?
if you really need it to be like this, move all your initialisation code into an async function just to make things easier to write:
async function start() {
const functionFolders = readdirSync("./src/functions");
for (const folder of functionFolders) {
const functionFiles = readdirSync(`./src/functions/${folder}`).filter(
(file) => file.endsWith(".js")
);
for (const file of functionFiles) {
const { default } = await import(`./functions/${folder}/${file}`);
default(client);
}
}
client.handleEvents();
client.handleCommands();
client.handleComponents();
client.login(TOKEN);
}
start();
for mongoose, what version are you using?
how can I know ?? I tried npm version but it don't show the version
type npm ls mongoose
thanks: mongoose@8.3.2
that seems to be the latest version
lemme try something on my side
ok 👍
this is my current repro, and the importing seems to work just fine
import { Mongoose } from 'mongoose';
import { Client } from 'discord.js';
import fs from 'fs/promises';
async function start() {
const mongoose = new Mongoose();
await mongoose.connect('mongodb://192.168.0.177:27017');
const client = new Client({
intents: [],
});
const configRaw = await fs.readFile('./config.json');
const config = JSON.parse(configRaw);
const { token } = config;
client.login(token);
client.on('ready', () => {
console.log('Connected.');
});
}
start();
I was just going to say, I converted one of my larger projects to ESM just a week or so ago and haven't had any issues with mongoose
thanks I'll test it
hi. How can I convert this into ESM ?
const event = require(`../../events/${folder}/${file}`);```
@flat sigil
you'll need to define require
Cause when I do
import event from `../../events/${folder}/${file}`
It says taht I can import only outside the module
so, import createRequire from node:module
and then const require = createRequire(import.meta.url);
whatt the hell...
So I do
import createRequire from WHAT ?
and then you can use require dynamically where a module doesn't export properly for ESM
import { createRequire } from "module"; ?
ok thanks
module, its built in to node but good practice is to prefix built in imports with node:
node:fs node:path node:process and so on
but thats what I had to do when I coverted to ESM because a package I use is CJS only
with no ESM alternative that I liked enough
It throws an error at:
const event = createRequire(`../../events/${folder}/${file}`);
throw new ERR_INVALID_ARG_VALUE('filename', filename,
^
TypeError [ERR_INVALID_ARG_VALUE]: The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received '../../events/client/interactionCreate.js'
at createRequire (node:internal/modules/cjs/loader:1514:13)
at client.handleEvents (file:///C:/Users/Waggerra/Documents/Discord/BOTS%20Discord/Tobor/src/functions/handlers/handleEvents.js:15:27)
at start (file:///C:/Users/Waggerra/Documents/Discord/BOTS%20Discord/Tobor/src/index.js:30:10) {
code: 'ERR_INVALID_ARG_VALUE'
}
hmm
whats the context of that require in your CJS code
is it like top level? or inside a function somewhere?
Inside a for loop
import { readdirSync } from "fs";
import { Mongoose } from "mongoose";
import { Client } from 'discord.js';
import { createRequire } from "module";
export default client => {
client.handleEvents = async () => {
const eventFolders = readdirSync("./src/events");
for (const folder of eventFolders) {
const eventFiles = readdirSync(`./src/events/${folder}`)
.filter((file) => file.endsWith(".js"));
switch (folder) {
case "client":
for (const file of eventFiles) {
const event = createRequire(`../../events/${folder}/${file}`);
if (event.once)
client.once(event.name, (...args) =>
event.execute(...args, client)
);
else
client.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
case "mongo":
for (const file of eventFiles) {
const event = createRequire(`../../events/${folder}/${file}`);
if (event.once)
connection.once(event.name, (...args) =>
event.execute(...args, client)
);
else
connection.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
default:
break;
}
}
};
};
ohhh
then just use import
import(<thepathhere>)
just that ?
you may need to use another ESM to CJS hack to get __dirname back as well
but I need to get the "event" value from the import
so I can do const event = import("`../../events/${folder}/${file}`")
or ```import event from ../../events/${folder}/${file}
neither
hold on
🤯 🫡
well technically the first one
but you'll need to await it
is event a named export in the file? or does it have a default export?
Srry but I don't understand (im new).
Actual code:
import { readdirSync } from "fs";
import { Mongoose } from "mongoose";
import { Client } from 'discord.js';
import { createRequire } from "module";
export default client => {
client.handleEvents = async () => {
const eventFolders = readdirSync("./src/events");
for (const folder of eventFolders) {
const eventFiles = readdirSync(`./src/events/${folder}`)
.filter((file) => file.endsWith(".js"));
switch (folder) {
case "client":
for (const file of eventFiles) {
const event = import(`../../events/${folder}/${file}`)
if (event.once)
client.once(event.name, (...args) =>
event.execute(...args, client)
);
else
client.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
case "mongo":
for (const file of eventFiles) {
const event = import(`../../events/${folder}/${file}`)
if (event.once)
connection.once(event.name, (...args) =>
event.execute(...args, client)
);
else
connection.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
default:
break;
}
}
};
};
how do you export event in the event file?
oh
export async function execute(interaction, client) {
export function execute() {
The first one for the "client" case, and the second one for mongo
you have two exported functions in the same file that are both called execute?
no. I mean, the "case name" = a folder, and it do some actions for each file inside that folder. So the first one is the export of a file in "client" folder, the second one for the mongo.
oh I see. ok, I mean inside the actual files themselves. so each file has one export called execute, right?
yes
oh well, InteractionCreate: (in client)
export async function execute(interaction, client) {```
ready:
export const once = true;
export async function execute(client) {```
In mongo:
Connected:
export function execute() {
console.log("[Database Status]: Connected!");
}```
Connecting:
export const name = "connecting";
export async function execute() {
console.log("[Database Status]: Connecting...");
}
ok then yeah thats fine. so as far as I can tell, all you need to do is const event = await import(filePathHere) and then event.execute(...args or whatever you want to send through)
ok thanks
let me know how you get on. I'm also still getting used to getting rid of stuff that can't be used in ESM
Thank you, it worked ! Now, I have a little mongodb problem. It says "connection" is not defined.
At line 34.
import { readdirSync } from "fs";
import { Mongoose } from "mongoose";
import { Client } from 'discord.js';
export default client => {
client.handleEvents = async () => {
const eventFolders = readdirSync("./src/events");
for (const folder of eventFolders) {
const eventFiles = readdirSync(`./src/events/${folder}`)
.filter((file) => file.endsWith(".js"));
switch (folder) {
case "client":
for (const file of eventFiles) {
const event = await import(`../../events/${folder}/${file}`)
if (event.once)
client.once(event.name, (...args) =>
event.execute(...args, client)
);
else
client.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
case "mongo":
for (const file of eventFiles) {
const event = await import(`../../events/${folder}/${file}`)
if (event.once)
connection.once(event.name, (...args) =>
event.execute(...args, client)
);
else
connection.on(event.name, (...args) =>
event.execute(...args, client)
);
}
break;
default:
break;
}
}
};
};
its at the end
I don't know how can I define it. Maybe ii can do something like const mongoose = Mongoose.new()
I don't see anywhere where you're defining it, yet you're importing Mongoose from mongoose and not using it. either use Mongoose.connection.on or just import connection from mongoose directly, thats what I do as I don't need all the other stuff
ok thanks ill test it

I'm getting this error:
throw new ERR_MODULE_NOT_FOUND(
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\Users\Waggerra\Documents\Discord\BOTS Discord\Tobor\src\schemas\guild' imported from C:\Users\Waggerra\Documents\Discord\BOTS Discord\Tobor\src\commands\tools\database.js
at finalizeResolution (node:internal/modules/esm/resolve:264:11)
at moduleResolve (node:internal/modules/esm/resolve:917:10)
at defaultResolve (node:internal/modules/esm/resolve:1130:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:396:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:365:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:240:38)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
at link (node:internal/modules/esm/module_job:84:36) {
code: 'ERR_MODULE_NOT_FOUND',
url: 'file:///C:/Users/Waggerra/Documents/Discord/BOTS%20Discord/Tobor/src/schemas/guild'
}```
The database.js script:
import { findOne, create } from "../../schemas/guild";
import { SlashCommandBuilder, Guild, PermissionFlagsBits } from "discord.js";
import { Types } from "mongoose";
export const data = new SlashCommandBuilder()
.setName("database")
.setDescription("Returns information from a database")
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator);
export async function execute(interaction, client) {
let guildData = await findOne({ guildId: interaction.guildId });
if (!guildData) {
guildData = await create({
_id: new Types.ObjectId(),
guildId: interaction.guild.id,
guildName: interaction.guild.name,
guildIcon: interaction.guild.iconURL()
? interaction.guild.iconURL()
: "None",
});
await guildData.save().catch(console.error);
await interaction?.reply({
content: `Server name: ${guildData.guildName}`,
});
console.log(guildData);
} else {
await interaction?.reply({
content: `Server ID: ${guildData.guildId}`,
});
console.log(guildData);
}
}
ESM modules need the file extension on the imports if the import is a local file
so import { findOne, create } from "../../schemas/guild"; becomes import { findOne, create } from "../../schemas/guild.js";
you'll need to do that with all imports in your project
but only where you import things you've eported in your own files
import { findOne, create } from "../../schemas/guild.js";
^^^^^^
SyntaxError: The requested module '../../schemas/guild.js' does not provide an export named 'create'
at ModuleJob._instantiate (node:internal/modules/esm/module_job:132:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:214:5)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async client.handleCommands (file:///C:/Users/Waggerra/Documents/Discord/BOTS%20Discord/Tobor/src/functions/handlers/handleCommands.js:15:25)```
[thinkgun](https://cdn.discordapp.com/emojis/1031569081696006164.webp?size=48&quality=lossless&name=thinkgun)
show the guild schema file
const { Schema, model } = require("mongoose");
const guildSchema = new Schema({
_id: Schema.Types.ObjectId,
guildId: String,
guildName: String,
guildIcon: { type: String, default: null, required: false },
});
module.exports = model("Guild", guildSchema, "guilds");
I think its because im using module.exports
well you need to get rid that require statement, everything in your project needs to be ESM so that means using import
so I remove the 'required' value ?
well const { variable } = require('module') is CJS syntax, your whole project needs to use the right syntax for ESM import { variable } from 'module'
at this point it might be better for you to find a good guide online that details how to move from CJS to ESM
I thought you were just having a few little after issues but it seems you still have lots of changes to make
yup I think so 😅
don't be discouraged though. everntually ESM will be the norm and CJS will fade so it's good to keep up if you can :)
thanks 🫡 😅
you said, How can I use __dirname in ESM ?
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
ok thanks !
That will replicate what __dirname does in CJS