Skip to content

Commit 8e6a395

Browse files
committed
feat: Switch from dynamic import to a more explicit approach
1 parent b54bfee commit 8e6a395

10 files changed

Lines changed: 48 additions & 119 deletions

File tree

src/commands/docs/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ApplicationCommandOptionType } from 'discord.js';
22
import { createCommands } from '../index.js';
33
import { type DocProvider, docProviders, executeDocCommand } from './providers.js';
44

5-
export default createCommands(
5+
export const docsCommands = createCommands(
66
Object.entries(docProviders).map(([providerKey, providerConfig]) => ({
77
data: {
88
name: providerKey,

src/commands/guides/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const loadChoices = async (): Promise<void> => {
1818

1919
await loadChoices();
2020

21-
export default createCommand(
21+
export const guidesCommand = createCommand(
2222
{
2323
name: 'guides',
2424
description: 'Get a guide on a specific subject',

src/commands/ping.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createCommand } from './index.js';
22

3-
export default createCommand(
3+
export const pingCommand = createCommand(
44
{
55
name: 'ping',
66
description: 'Replies with Pong!',

src/commands/tips/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,4 @@ const contextMenuCommands = Array.from(subjectChoices).map(([key, value]) =>
9292
)
9393
);
9494

95-
export default [slashCommand, ...contextMenuCommands];
95+
export const tipsCommands = [slashCommand, ...contextMenuCommands];

src/events/has-var.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const hasVarDeclaration = (code: string, language: string): boolean => {
3737
}
3838
};
3939

40-
export default createEvent(
40+
export const hasVarEvent = createEvent(
4141
{
4242
name: Events.MessageCreate,
4343
once: false,

src/events/interaction-create.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { Events } from 'discord.js';
2-
import { getCommands } from '../util/loaders.js';
2+
import { commands } from '../util/loaders.js';
33
import { createEvent } from './index.js';
44

5-
const commands = await getCommands(new URL('../commands/', import.meta.url));
6-
7-
export default createEvent(
5+
export const interactionCreateEvent = createEvent(
86
{
97
name: Events.InteractionCreate,
108
},

src/events/just-ask.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const [response] = await loadMarkdownOptions<{ name: string }>(
3333

3434
const { canRun, reset } = rateLimit(10 * MINUTE);
3535

36-
export default createEvent(
36+
export const justAskEvent = createEvent(
3737
{
3838
name: Events.MessageCreate,
3939
},

src/events/ready.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Events } from 'discord.js';
22
import { createEvent } from './index.js';
33

4-
export default createEvent(
4+
export const readyEvent = createEvent(
55
{
66
name: Events.ClientReady,
77
once: true,

src/index.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ActivityType, Client, GatewayIntentBits } from 'discord.js';
22
import { config } from './env.js';
3-
import { getCommands, getEvents, loadCommands, loadEvents } from './util/loaders.js';
3+
import { commands, events, registerCommands, registerEvents } from './util/loaders.js';
44

55
// Create a new client instance
66
const client = new Client({
@@ -22,13 +22,8 @@ const client = new Client({
2222
},
2323
});
2424

25-
// Load events and commands
26-
const events = await getEvents(new URL('events/', import.meta.url));
27-
const commands = await getCommands(new URL('commands/', import.meta.url));
28-
29-
// use path utils etc to get the paths
30-
31-
await loadEvents(client, events);
32-
await loadCommands(client, commands);
25+
// Register events and commands
26+
await registerEvents(client, events);
27+
await registerCommands(client, commands);
3328

3429
void client.login(config.discord.token);

src/util/loaders.ts

Lines changed: 35 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,27 @@
1-
import type { PathLike } from 'node:fs';
2-
import { readdir, stat } from 'node:fs/promises';
31
import type { Client } from 'discord.js';
2+
import { docsCommands } from '../commands/docs/index.js';
3+
import { guidesCommand } from '../commands/guides/index.js';
44
import { type Command, predicate as commandPredicate } from '../commands/index.js';
5+
import { pingCommand } from '../commands/ping.js';
6+
import { tipsCommands } from '../commands/tips/index.js';
7+
import { hasVarEvent } from '../events/has-var.js';
58
import { type DiscordEvent, predicate as eventPredicate } from '../events/index.js';
9+
import { interactionCreateEvent } from '../events/interaction-create.js';
10+
import { justAskEvent } from '../events/just-ask.js';
11+
import { readyEvent } from '../events/ready.js';
612

713
/**
814
* A predicate to check if the structure is valid
915
*/
1016
export type StructurePredicate<T> = (structure: unknown) => structure is T;
1117

1218
/**
13-
* Loads all structures in the provided directory
14-
*
15-
* @param dir - The directory to load the structures from
16-
* @param predicate - The predicate to check if the structure is valid
17-
* @param recursive- Whether to load structures recursively
18-
* @returns
19-
*/
20-
export const loadStructures = async <T>(
21-
dir: PathLike,
22-
predicate: StructurePredicate<T>,
23-
recursive = true
24-
): Promise<T[]> => {
25-
const statDir = await stat(dir);
26-
27-
if (!statDir.isDirectory()) {
28-
throw new Error(`The path ${dir} is not a directory`);
29-
}
30-
31-
// Get all files in the directory
32-
const files = await readdir(dir);
33-
34-
// Create an empty array to store the structures
35-
const structures: T[] = [];
36-
37-
// Loop through all files in the directory
38-
for (const file of files) {
39-
const fileUrl = new URL(`${dir}/${file}`, import.meta.url);
40-
41-
// Get the stats of the file
42-
const fileStat = await stat(fileUrl);
43-
44-
// If the file is a directory and recursive is true, load the structures in the directory
45-
if (fileStat.isDirectory() && recursive) {
46-
structures.push(...(await loadStructures(fileUrl, predicate, recursive)));
47-
continue;
48-
}
49-
50-
// If the file is index.js or the file does not end with .js, skip it
51-
if (
52-
// file === 'index.js' ||
53-
// file === 'index.ts' ||
54-
!file.endsWith('.js') &&
55-
!file.endsWith('.ts')
56-
) {
57-
continue;
58-
}
59-
60-
// Import the structure from the file
61-
const { default: structure } = await import(fileUrl.href);
62-
63-
// If the structure is an array, loop through all structures in the array and check if they are valid
64-
// If the structure is not an array, check if it is valid
65-
if (Array.isArray(structure)) {
66-
for (const str of structure) {
67-
if (predicate(str)) {
68-
structures.push(str);
69-
}
70-
}
71-
} else if (predicate(structure)) {
72-
structures.push(structure);
73-
}
74-
}
75-
return structures;
76-
};
77-
78-
/**
79-
* Gets all the commands in the provided directory
80-
*
81-
* @param dir - The directory to load the commands from
82-
* @param recursive - Whether to load commands recursively
83-
* @returns A map of command names to commands
84-
*/
85-
export const getCommands = async (
86-
dir: PathLike,
87-
recursive = true
88-
): Promise<Map<string, Command>> => {
89-
const commands = await loadStructures<Command>(dir, commandPredicate, recursive);
90-
91-
return new Map(commands.map((command) => [command.data.name, command]));
92-
};
93-
94-
/**
95-
* Gets all the events in the provided directory
96-
*
97-
* @param dir - The directory to load the events from
98-
* @param recursive - Whether to load events recursively
99-
* @returns An array of events
100-
*/
101-
export const getEvents = async (dir: PathLike, recursive = true): Promise<DiscordEvent[]> => {
102-
return loadStructures(dir, eventPredicate, recursive);
103-
};
104-
105-
/**
106-
* Loads commands to the Discord API
19+
* Register commands to the Discord API
10720
*
10821
* @param client - The Discord client
10922
* @param commands - A map of command names to commands
11023
*/
111-
export const loadCommands = async (
24+
export const registerCommands = async (
11225
client: Client,
11326
commands: Map<string, Command>
11427
): Promise<void> => {
@@ -128,12 +41,12 @@ export const loadCommands = async (
12841
};
12942

13043
/**
131-
* Loads events to the Discord client
44+
* Register events to the Discord client
13245
*
13346
* @param client - The Discord client
13447
* @param events - An array of events
13548
*/
136-
export const loadEvents = async (client: Client, events: DiscordEvent[]): Promise<void> => {
49+
export const registerEvents = async (client: Client, events: DiscordEvent[]): Promise<void> => {
13750
// Loop through all events
13851
for (const event of events) {
13952
console.log(`Loading event: ${event.name}`);
@@ -148,3 +61,26 @@ export const loadEvents = async (client: Client, events: DiscordEvent[]): Promis
14861
});
14962
}
15063
};
64+
65+
/**
66+
*
67+
* @returns An array of events
68+
*/
69+
const loadEvents = (): DiscordEvent[] => {
70+
const events = [hasVarEvent, readyEvent, justAskEvent, interactionCreateEvent].filter(
71+
eventPredicate
72+
);
73+
return events as DiscordEvent[];
74+
};
75+
76+
/**
77+
*
78+
* @returns A map of command names to commands
79+
*/
80+
const loadCommands = (): Map<string, Command> => {
81+
const commands = [pingCommand, tipsCommands, guidesCommand, docsCommands].flat();
82+
return new Map(commands.filter(commandPredicate).map((command) => [command.data.name, command]));
83+
};
84+
85+
export const commands = loadCommands();
86+
export const events = loadEvents();

0 commit comments

Comments
 (0)