discordx: [Bug]: can't pass classes to client constructor with "type": "module"

What happened?

I’m working on an esm-only project (one of my dependencies requires it and it’s viral so I must use it too) and tried passing a glob that’s used to find @Discord() classes.

Node complains about require not being supported with "type": "module" (I believe this is the problematic code).

I also can’t seem to pass a list of class objects anymore (coming from @typeit/discord), is that on purpose? Because that would solve this issue as well.

Reproduction

In package.json:

// ...
"type": "module",
// ...

In src/index.ts:

import discordx from 'discordx';
const {Client} = discordx;

const discordClient = new Client({
  botId: 'test',
  classes: [path.resolve(getDirname(), 'discords/*.{ts,js}')], // getDirname is __dirname for esm, you can assume it works the same. 
  silent: false,
  intents: [/* ... */],
});

Run like this:

$ node --loader ts-node/esm/transpile-only src/index.ts

Actually doing the dynamic loading of classes shouldn’t be too hard (just use import()), but I’m not sure how I would conditionally do this or require() in commonjs mode. Maybe use the newer syntax and rely on the typescript compiler to produce commonjs-compatible code?

Version

Dev

Relevant log output

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/ohmree/code/js/contest_buddy/packages/server/src/discords/app-discord.ts
require() of ES modules is not supported.
require() of /home/ohmree/code/js/contest_buddy/packages/server/src/discords/app-discord.ts from /home/ohmree/code/js/contest_buddy/node_modules/.pnpm/discordx@9.0.0-dev.1636374790.51b604b/node_modules/discordx/build/logic/metadatas/MetadataStorage.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules.
Instead change the requiring code to use import(), or remove "type": "module" from /home/ohmree/code/js/contest_buddy/packages/server/package.json.

Code of Conduct

  • I agree to follow this project’s Code of Conduct

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 22 (10 by maintainers)

Most upvoted comments

What about passing the actual imported classes instead of glob strings? Is that a planned feature or was it removed for a reason?

passing the actual class? you mean hard coding them? glob isn’t an issue, i should fix this tonight for you

Something like this:

// discords/app-discord.ts
@Discord()
abstract class AppDiscord { /* ... */ }
export default AppDiscord;
// index.ts
import AppDiscord from 'discords/app-discord.js';
const client = new Client({classes: [AppDiscord]});

because hard coding a massive list of files is a pain, and importing them all at startup can cause serious circular dependency issues

I see. Well, as long as there’s a legitimate reason for this change it’s okay.

been meaning to fix this for a while. i will raise a PR tonight and hopefully get this sorted for ES modules only people (assuming DJS or any module from any plugin we use doesn’t have a require statement) and if it does, then we will have to wait until TS 4.5, i have this issue with NodeFetch