Skip to content

Conversation

@ManInTheHam
Copy link

Closes #11346

This PR implements Bun templates for the create-discord-bot package:

  • Added TypeScript Bun template with complete src structure and configuration
  • Added JavaScript Bun template with complete src structure and configuration
  • Both templates mirror the Node.js versions with Bun-specific configuration

The templates include:

  • src/index.ts / src/index.js - Main bot entry point
  • src/util/deploy.ts / src/util/deploy.js - Command deployment utility
  • package.json with Bun-specific scripts
  • Full TypeScript/ESLint configuration

- Add TypeScript Bun template with complete src structure
- Add JavaScript Bun template with complete src structure
- Both templates mirror the Node.js versions with Bun-specific configuration

Closes discordjs#11346
@vercel
Copy link

vercel bot commented Dec 9, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
discord-js Skipped Skipped Dec 9, 2025 2:47pm
discord-js-guide Skipped Skipped Dec 9, 2025 2:47pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

📝 Walkthrough

Walkthrough

This PR implements Bun bot templates for create-discord-bot by adding complete boilerplate code including configuration files, command handlers, event listeners, utility loaders, and bot initialization scripts for both JavaScript and TypeScript variants.

Changes

Cohort / File(s) Summary
Configuration & Formatting
packages/create-discord-bot/template/Bun/JavaScript/.gitignore, .prettierignore, .prettierrc.json
packages/create-discord-bot/template/Bun/TypeScript/.gitignore, .prettierignore, .prettierrc.json
Added .gitignore with common Node.js/Bun patterns (node_modules, dist, .env, .DS_Store, \*.log). Added .prettierignore to exclude pnpm-lock.yaml from formatting. Added .prettierrc.json with consistent formatting rules (printWidth 120, useTabs true, singleQuote true, trailingComma all).
Command Definitions
packages/create-discord-bot/template/Bun/JavaScript/src/commands/index.js
packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts
Added Command schema and type validation using Zod. Exports schema (runtime validator) and predicate (type guard) to identify valid Command objects with data and execute function.
Command Modules
packages/create-discord-bot/template/Bun/JavaScript/src/commands/ping.js, utility/user.js
packages/create-discord-bot/template/Bun/TypeScript/src/commands/ping.ts, utility/user.ts
Implemented ping command (responds with 'Pong!') and user command (displays invoking user's username). Both follow Command structure with data (name, description) and async execute handler.
Event Definitions
packages/create-discord-bot/template/Bun/JavaScript/src/events/index.js
packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts
Added Event schema and type validation using Zod. Exports schema (runtime validator) and predicate (type guard) to identify valid Event objects with name, optional once flag, and execute function.
Event Handlers
packages/create-discord-bot/template/Bun/JavaScript/src/events/ready.js
packages/create-discord-bot/template/Bun/TypeScript/src/events/ready.ts
Added ClientReady event handler that logs bot login info once on startup. Implements Event interface with name, once: true, and execute handler.
Interaction Router
packages/create-discord-bot/template/Bun/JavaScript/src/events/interactionCreate.js
packages/create-discord-bot/template/Bun/TypeScript/src/events/interactionCreate.ts
Added InteractionCreate event handler that dynamically loads commands at module initialization, routes incoming command interactions to corresponding command handlers by name, and throws error for missing commands.
Utility Loaders
packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts
Implemented loadStructures() for dynamic module discovery with predicate filtering. Specialized loaders: loadCommands() returns Map keyed by command name, loadEvents() returns Event array. Supports recursive directory traversal, skips index.js/ts, uses glob patterns.
Deployment Script
packages/create-discord-bot/template/Bun/JavaScript/src/util/deploy.js
packages/create-discord-bot/template/Bun/TypeScript/src/util/deploy.ts
Added deployment script that loads commands, extracts command data, initializes Discord REST client, and performs bulk overwrite of global application commands via Discord API.
Bot Entry Points
packages/create-discord-bot/template/Bun/JavaScript/src/index.js
packages/create-discord-bot/template/Bun/TypeScript/src/index.ts
Implemented bot initialization: creates Discord Client with GuildMember intent, dynamically loads events, registers event handlers (using once/on based on Event.once flag), wraps execution in try/catch for error logging, and logs in using DISCORD_TOKEN environment variable.

Sequence Diagram(s)

sequenceDiagram
    participant Main as Bot Entry Point
    participant Discord as Discord Client
    participant EventMgr as Event Manager
    participant CmdLoader as Command Loader
    participant Interaction
    participant CmdRouter as InteractionCreate Handler
    participant Command as Command Handler

    Main->>Main: Load Events (top-level await)
    Main->>EventMgr: Register all loaded events<br/>(once/on based on flag)
    Main->>Discord: Client.login(DISCORD_TOKEN)
    Note over Main: Bot initialization complete

    Interaction->>Discord: Dispatch InteractionCreate
    Discord->>CmdRouter: Execute InteractionCreate handler
    CmdRouter->>CmdRouter: Load Commands (cached)
    CmdRouter->>CmdRouter: Check if interaction.isCommand()
    alt Is Command
        CmdRouter->>CmdRouter: Lookup command by name
        alt Command Found
            CmdRouter->>Command: command.execute(interaction)
            Command->>Interaction: interaction.reply()
        else Command Not Found
            CmdRouter->>CmdRouter: throw error
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

  • Loaders module (loaders.js/ts): Complex async module discovery with glob patterns, recursive traversal, and predicate-based filtering requires careful verification of file discovery logic and error handling.
  • InteractionCreate handler (interactionCreate.js/ts): Dynamic command loading at module level and command routing logic need verification for correctness and edge cases (missing commands, non-command interactions).
  • Bot initialization (index.js/ts): Event registration with conditional once/on dispatch and error wrapping requires review of Discord.js integration and event flow.
  • High file count across variants: Dual JavaScript/TypeScript implementations increase total review surface area; verify consistency between variants.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add Bun templates for create-discord-bot' clearly and directly describes the main change: adding Bun templates to the create-discord-bot package.
Description check ✅ Passed The description is directly related to the changeset, providing context about the issue being closed and detailing the Bun templates added for both TypeScript and JavaScript variants.
Linked Issues check ✅ Passed The PR successfully addresses issue #11346 by implementing complete Bun templates (TypeScript and JavaScript) with full src structure, utilities, and configuration files mirroring the Node.js versions.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing Bun templates: configuration files (.prettierignore, .prettierrc.json, .gitignore), command modules with schemas and predicates, event handlers, loaders, and deployment utilities for both TypeScript and JavaScript variants.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel vercel bot temporarily deployed to Preview – discord-js December 9, 2025 13:08 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide December 9, 2025 13:08 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06c8da2 and 58864c3.

📒 Files selected for processing (23)
  • packages/create-discord-bot/template/Bun/JavaScript/.prettierignore (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/.prettierrc.json (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/commands/index.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/commands/ping.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/commands/utility/user.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/events/index.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/events/interactionCreate.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/events/ready.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/index.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/util/deploy.js (1 hunks)
  • packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/.gitignore (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/.prettierignore (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/.prettierrc.json (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/commands/ping.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/commands/utility/user.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/events/interactionCreate.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/events/ready.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/index.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/util/deploy.ts (1 hunks)
  • packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (11)
packages/create-discord-bot/template/Bun/TypeScript/src/events/ready.ts (2)
packages/create-discord-bot/template/Bun/JavaScript/src/index.js (1)
  • client (7-7)
packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts (1)
  • Event (8-25)
packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (3)
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (3)
  • loadStructures (21-58)
  • loadCommands (60-65)
  • loadEvents (67-69)
packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts (1)
  • predicate (32-33)
packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts (1)
  • predicate (39-40)
packages/create-discord-bot/template/Bun/JavaScript/src/events/interactionCreate.js (2)
packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (1)
  • loadCommands (64-69)
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (1)
  • loadCommands (60-65)
packages/create-discord-bot/template/Bun/JavaScript/src/events/ready.js (1)
packages/create-discord-bot/template/Bun/JavaScript/src/index.js (1)
  • client (7-7)
packages/create-discord-bot/template/Bun/TypeScript/src/commands/ping.ts (1)
packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts (1)
  • Command (8-19)
packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts (2)
packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts (2)
  • schema (30-34)
  • predicate (39-40)
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (1)
  • StructurePredicate (11-11)
packages/create-discord-bot/template/Bun/TypeScript/src/index.ts (3)
packages/create-discord-bot/template/Bun/JavaScript/src/index.js (2)
  • client (7-7)
  • events (10-10)
packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (1)
  • loadEvents (76-78)
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (1)
  • loadEvents (67-69)
packages/create-discord-bot/template/Bun/TypeScript/src/util/deploy.ts (3)
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (1)
  • loadCommands (60-65)
packages/rest/src/lib/REST.ts (1)
  • REST (37-478)
packages/core/src/api/index.ts (1)
  • API (40-97)
packages/create-discord-bot/template/Bun/TypeScript/src/commands/utility/user.ts (1)
packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts (1)
  • Command (8-19)
packages/create-discord-bot/template/Bun/TypeScript/src/events/interactionCreate.ts (3)
packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (1)
  • loadCommands (64-69)
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (1)
  • loadCommands (60-65)
packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts (1)
  • Event (8-25)
packages/create-discord-bot/template/Bun/JavaScript/src/index.js (1)
packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (1)
  • loadEvents (76-78)
🔇 Additional comments (26)
packages/create-discord-bot/template/Bun/TypeScript/.gitignore (1)

1-5: Verify .gitignore completeness against Node.js template and Bun-specific patterns.

The .gitignore covers common Node.js artifacts (node_modules/, dist/, .env, .DS_Store, *.log), but needs verification:

  1. Does the existing Node.js template .gitignore include additional patterns (IDE-specific files, .env variants)?
  2. Should Bun-specific patterns be added (e.g., .bun or .cache directories if Bun's build tools generate them)?

Since the PR objective states templates should be "similar to the existing Node.js templates," ensure this matches the Node.js TypeScript template's .gitignore.

packages/create-discord-bot/template/Bun/JavaScript/.prettierignore (1)

1-1: LGTM!

Standard practice to exclude lock files from Prettier formatting.

packages/create-discord-bot/template/Bun/JavaScript/.prettierrc.json (1)

1-9: LGTM!

Well-structured Prettier configuration with appropriate settings for the template.

packages/create-discord-bot/template/Bun/TypeScript/.prettierrc.json (1)

1-9: LGTM!

Configuration is consistent with the JavaScript template, ensuring uniform formatting across both Bun templates.

packages/create-discord-bot/template/Bun/TypeScript/src/commands/utility/user.ts (1)

1-11: Command structure is correct.

The implementation correctly conforms to the Command interface and follows the established pattern in the template.

packages/create-discord-bot/template/Bun/TypeScript/src/util/deploy.ts (1)

1-8: Command loading and registration logic looks good.

The script correctly loads commands, extracts their data, and prepares them for bulk registration.

packages/create-discord-bot/template/Bun/JavaScript/src/index.js (1)

12-24: Event registration and bot initialization look good.

The implementation correctly:

  • Distinguishes between once and on event handlers
  • Wraps event execution in try/catch to prevent unhandled promise rejections
  • Uses void to explicitly handle the unawaited login Promise
packages/create-discord-bot/template/Bun/TypeScript/src/index.ts (2)

1-4: LGTM! Import structure is correct.

The imports are properly structured for Bun's TypeScript runtime, including the .ts extension in the loadEvents import which Bun supports.


13-21: LGTM! Event handler registration with proper error handling.

The event registration logic correctly handles both once and on events, and includes try/catch for individual event execution failures.

packages/create-discord-bot/template/Bun/JavaScript/src/commands/utility/user.js (1)

1-10: LGTM! Simple and correct command implementation.

The command structure is correct with proper JSDoc type annotation, and the execute function appropriately replies with the user's username.

packages/create-discord-bot/template/Bun/TypeScript/src/events/ready.ts (1)

1-10: LGTM! Proper TypeScript event handler with satisfies.

The event handler correctly implements the Event<Events.ClientReady> contract using the satisfies operator for type safety while preserving literal types.

packages/create-discord-bot/template/Bun/JavaScript/src/commands/ping.js (1)

1-10: LGTM! Simple and correct ping command.

The command structure is correct with proper JSDoc type annotation, and appropriately replies with "Pong!".

packages/create-discord-bot/template/Bun/JavaScript/src/commands/index.js (1)

1-25: LGTM! Clean validation infrastructure.

The Command validation system using Zod provides runtime type safety and integrates well with the loader utilities.

packages/create-discord-bot/template/Bun/JavaScript/src/events/ready.js (1)

1-10: LGTM! Correct event handler implementation.

The event handler correctly implements the ClientReady event with proper JSDoc type annotation and appropriate logging.

packages/create-discord-bot/template/Bun/TypeScript/src/commands/ping.ts (1)

1-11: LGTM! Type-safe command implementation.

The command correctly uses the satisfies Command operator to ensure type safety while preserving literal types for the data object.

packages/create-discord-bot/template/Bun/TypeScript/src/events/interactionCreate.ts (1)

1-6: LGTM on imports and command loading.

The top-level await pattern for loading commands at module initialization is appropriate for Bun/ES modules and ensures commands are ready before any interaction is processed.

packages/create-discord-bot/template/Bun/JavaScript/src/events/index.js (1)

1-29: Well-structured event schema and validation.

The zod schema correctly validates the Event structure, and using safeParse for the predicate is the right approach for non-throwing validation. The JSDoc typedef provides good type hints for JavaScript users.

packages/create-discord-bot/template/Bun/TypeScript/src/events/index.ts (1)

1-40: Clean type definitions with good documentation.

The generic Event type with proper constraints, comprehensive JSDoc, and the runtime validation schema provide both compile-time and runtime safety. The implementation is consistent with the JavaScript counterpart.

packages/create-discord-bot/template/Bun/TypeScript/src/commands/index.ts (1)

1-33: LGTM!

The Command type is well-defined with proper discord.js types. The zod schema provides adequate runtime shape validation, and the pattern is consistent with the events module.

packages/create-discord-bot/template/Bun/JavaScript/src/events/interactionCreate.js (1)

7-8: Good use of JSDoc for type annotation.

The JSDoc type annotation correctly references the Event type from the index module, providing type safety in JavaScript.

packages/create-discord-bot/template/Bun/JavaScript/src/util/loaders.js (3)

23-57: LGTM!

The loadStructures function correctly:

  • Validates that the provided path is a directory
  • Handles both URL and string paths
  • Uses glob patterns to find .js files recursively (when enabled)
  • Skips index.js to avoid circular imports
  • Dynamically imports and validates structures using the predicate

64-78: LGTM!

The loadCommands and loadEvents functions correctly wrap loadStructures with appropriate predicates. The reduce pattern for building the command Map by name is idiomatic and matches the TypeScript template implementation.


1-5: No action needed. Bun fully implements and supports the node:fs/promises.glob API, including all standard options (pattern strings/arrays, exclude, withFileTypes). Using fs/promises.glob is appropriate for a Bun template as it maintains compatibility with Node.js while working seamlessly in Bun's runtime.

packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts (3)

1-6: Verify Bun compatibility with node:fs/promises glob API.

Same concern as the JavaScript variant: the glob function from node:fs/promises is a Node.js 22+ API. Consider using Bun's native glob functionality (Bun.glob()) for better compatibility and performance in this Bun-specific template.

The .ts import extensions on lines 5-6 are correct for Bun's native TypeScript support.


21-58: LGTM!

The generic loadStructures function is well-typed and correctly implements:

  • Directory validation with clear error messaging
  • URL/string path handling
  • Recursive glob pattern construction for .ts files
  • Index file exclusion to prevent circular imports
  • Dynamic import with predicate validation

The implementation aligns with the established pattern from the relevant code snippets.


60-69: LGTM!

Both loadCommands and loadEvents are properly typed and follow the same pattern as the reference TypeScript implementation. The Map reduction for commands correctly keys by cur.data.name.

Comment on lines +10 to +19
async execute(interaction) {
if (interaction.isCommand()) {
const command = commands.get(interaction.commandName);

if (!command) {
throw new Error(`Command '${interaction.commandName}' not found.`);
}

await command.execute(interaction);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Same issue: throwing leaves the interaction unacknowledged.

This has the same problem as the TypeScript version. The thrown error will cause the interaction to timeout without user feedback.

 	async execute(interaction) {
 		if (interaction.isCommand()) {
 			const command = commands.get(interaction.commandName);

 			if (!command) {
-				throw new Error(`Command '${interaction.commandName}' not found.`);
+				console.error(`Command '${interaction.commandName}' not found.`);
+				await interaction.reply({ content: 'Unknown command.', ephemeral: true });
+				return;
 			}

 			await command.execute(interaction);
 		}
 	},
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async execute(interaction) {
if (interaction.isCommand()) {
const command = commands.get(interaction.commandName);
if (!command) {
throw new Error(`Command '${interaction.commandName}' not found.`);
}
await command.execute(interaction);
}
async execute(interaction) {
if (interaction.isCommand()) {
const command = commands.get(interaction.commandName);
if (!command) {
console.error(`Command '${interaction.commandName}' not found.`);
await interaction.reply({ content: 'Unknown command.', ephemeral: true });
return;
}
await command.execute(interaction);
}
},
🤖 Prompt for AI Agents
In
packages/create-discord-bot/template/Bun/JavaScript/src/events/interactionCreate.js
around lines 10 to 19, do not throw when a command is missing or when
command.execute fails because that leaves the interaction unacknowledged;
instead, if commands.get(...) returns falsy, send an ephemeral reply to the
interaction indicating the command was not found and return; wrap
command.execute(interaction) in a try/catch and in the catch send an error
response: if interaction.deferred or interaction.replied use
interaction.followUp({ content: 'An error occurred while executing that
command.', ephemeral: true }) else use interaction.reply({ content: 'An error
occurred while executing that command.', ephemeral: true }); ensure you return
after responding so the event handler completes.

Comment on lines +9 to +10
// Load the events and commands
const events = await loadEvents(new URL('events/', import.meta.url));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Comment is slightly misleading.

The comment says "Load the events and commands" but only events are loaded here. Commands are loaded within the interactionCreate event handler.

-// Load the events and commands
+// Load the events
 const events = await loadEvents(new URL('events/', import.meta.url));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Load the events and commands
const events = await loadEvents(new URL('events/', import.meta.url));
// Load the events
const events = await loadEvents(new URL('events/', import.meta.url));
🤖 Prompt for AI Agents
In packages/create-discord-bot/template/Bun/JavaScript/src/index.js around lines
9-10, the inline comment "Load the events and commands" is misleading because
only events are loaded at this call; commands are loaded later inside the
interactionCreate handler. Update the comment to accurately reflect behavior
(e.g., "Load the events" or "Load the events (commands are loaded in
interactionCreate)") so it matches the code flow.

const commands = await loadCommands(new URL('../commands/', import.meta.url));
const commandData = [...commands.values()].map((command) => command.data);

const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add validation for required environment variables.

The DISCORD_TOKEN environment variable is accessed without validation. If undefined, the REST client will fail with an unclear error message.

Apply this diff to add validation:

+if (!process.env.DISCORD_TOKEN || !process.env.APPLICATION_ID) {
+	throw new Error('Missing required environment variables: DISCORD_TOKEN and APPLICATION_ID must be set.');
+}
+
 const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
if (!process.env.DISCORD_TOKEN || !process.env.APPLICATION_ID) {
throw new Error('Missing required environment variables: DISCORD_TOKEN and APPLICATION_ID must be set.');
}
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
🤖 Prompt for AI Agents
In packages/create-discord-bot/template/Bun/JavaScript/src/util/deploy.js around
line 10, the code uses process.env.DISCORD_TOKEN directly when creating the REST
client; add a validation step before this line that checks for a non-empty
DISCORD_TOKEN and fails fast with a clear error (throw or console.error +
process.exit(1)) if it's missing; update the code to read the token into a local
const after validation and use that const when calling new
REST(...).setToken(...), optionally doing the same pattern for any other
required env vars.

const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
const api = new API(rest);

const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID, commandData);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for the API call.

The bulkOverwriteGlobalCommands call has no error handling. If registration fails (e.g., invalid token, network error, malformed command data), the script will crash with a potentially unclear error message.

Apply this diff to add error handling:

-const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID, commandData);
-
-console.log(`Successfully registered ${result.length} commands.`);
+try {
+	const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID, commandData);
+	console.log(`Successfully registered ${result.length} commands.`);
+} catch (error) {
+	console.error('Failed to register commands:', error);
+	process.exit(1);
+}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/create-discord-bot/template/Bun/JavaScript/src/util/deploy.js around
line 13, the call to api.applicationCommands.bulkOverwriteGlobalCommands lacks
error handling; wrap this async call in a try/catch, log a clear error message
including the caught error and relevant context (e.g., APPLICATION_ID and number
of commands), and exit or rethrow with a non-zero status so failures are
surfaced clearly; also validate that process.env.APPLICATION_ID exists before
calling and handle that case with a logged error and early exit.

description: 'Provides information about the user.',
},
async execute(interaction) {
await interaction.reply(`This command was run bu ${interaction.user.username}.`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo in reply message.

"bu" should be "by".

-		await interaction.reply(`This command was run bu ${interaction.user.username}.`);
+		await interaction.reply(`This command was run by ${interaction.user.username}.`);
🤖 Prompt for AI Agents
In
packages/create-discord-bot/template/Bun/TypeScript/src/commands/utility/user.ts
around line 9, the reply message contains a typo: "This command was run bu ..."
— change "bu" to "by" so the string reads "This command was run by
${interaction.user.username}." and ensure punctuation remains correct.

Comment on lines +10 to +19
async execute(interaction) {
if (interaction.isCommand()) {
const command = commands.get(interaction.commandName);

if (!command) {
throw new Error(`Command '${interaction.commandName}' not found.`);
}

await command.execute(interaction);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Throwing an unhandled error will crash the bot or timeout the interaction.

When a command isn't found, throwing an error leaves the interaction unacknowledged, causing Discord to show "The application did not respond" to the user. Additionally, unhandled exceptions in event handlers can destabilize the bot.

Consider replying with an ephemeral error message instead:

 	async execute(interaction) {
 		if (interaction.isCommand()) {
 			const command = commands.get(interaction.commandName);

 			if (!command) {
-				throw new Error(`Command '${interaction.commandName}' not found.`);
+				console.error(`Command '${interaction.commandName}' not found.`);
+				await interaction.reply({ content: 'Unknown command.', ephemeral: true });
+				return;
 			}

 			await command.execute(interaction);
 		}
 	},
🤖 Prompt for AI Agents
In
packages/create-discord-bot/template/Bun/TypeScript/src/events/interactionCreate.ts
around lines 10–19, do not throw when a command is missing: instead detect
missing command and reply to the interaction with an ephemeral error message (or
if the interaction was already deferred, use followUp) so the user sees a
response; wrap command execution in a try/catch, log the error, and send an
ephemeral generic error reply on exceptions (checking
interaction.replied/interaction.deferred and using interaction.reply or
interaction.followUp accordingly) to avoid leaving the interaction
unacknowledged and prevent unhandled exceptions from crashing the bot.

}

// Login to the client
void client.login(process.env.DISCORD_TOKEN);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add validation and error handling for client login.

Two issues:

  1. DISCORD_TOKEN is accessed without validation - if undefined, login will fail with an unclear error
  2. Using void discards the login promise, preventing error handling for login failures

Apply this diff to add validation and proper error handling:

-// Login to the client
-void client.login(process.env.DISCORD_TOKEN);
+// Validate environment variable
+if (!process.env.DISCORD_TOKEN) {
+	throw new Error('Missing required environment variable: DISCORD_TOKEN must be set.');
+}
+
+// Login to the client
+client.login(process.env.DISCORD_TOKEN).catch((error) => {
+	console.error('Failed to login:', error);
+	process.exit(1);
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void client.login(process.env.DISCORD_TOKEN);
// Validate environment variable
if (!process.env.DISCORD_TOKEN) {
throw new Error('Missing required environment variable: DISCORD_TOKEN must be set.');
}
// Login to the client
client.login(process.env.DISCORD_TOKEN).catch((error) => {
console.error('Failed to login:', error);
process.exit(1);
});
🤖 Prompt for AI Agents
In packages/create-discord-bot/template/Bun/TypeScript/src/index.ts around line
24, the code calls client.login(process.env.DISCORD_TOKEN) without validating
the env var and discards the returned promise with void; change this to first
validate that process.env.DISCORD_TOKEN is present and otherwise log an error
and exit, then await the login promise inside a try/catch (or use .catch) so
login failures are handled: on success continue, on failure log the error and
exit with non-zero status. Ensure the function is async or the top-level handles
the promise so you don't drop the returned promise.

Comment on lines +10 to +13
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN!);
const api = new API(rest);

const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID!, commandData);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check Node.js templates for env var handling patterns
echo "=== Node.js TypeScript template ==="
rg -n "process\.env\." packages/create-discord-bot/template/TypeScript/src/util/deploy.ts 2>/dev/null || echo "File not found or no matches"

echo ""
echo "=== Node.js JavaScript template ==="
rg -n "process\.env\." packages/create-discord-bot/template/JavaScript/src/util/deploy.js 2>/dev/null || echo "File not found or no matches"

echo ""
echo "=== Bun TypeScript template (for comparison) ==="
rg -n "process\.env\." packages/create-discord-bot/template/Bun/TypeScript/src/util/deploy.ts 2>/dev/null || echo "File not found or no matches"

Repository: discordjs/discord.js

Length of output: 184


Add explicit validation for environment variables with clear error messages.

Non-null assertions on process.env.DISCORD_TOKEN and process.env.APPLICATION_ID will cause cryptic errors if these required variables are missing at runtime. Validating upfront and throwing descriptive errors improves developer experience:

+const token = process.env.DISCORD_TOKEN;
+const applicationId = process.env.APPLICATION_ID;
+
+if (!token) {
+	throw new Error('DISCORD_TOKEN environment variable is required');
+}
+
+if (!applicationId) {
+	throw new Error('APPLICATION_ID environment variable is required');
+}
+
-const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN!);
+const rest = new REST({ version: '10' }).setToken(token);
 const api = new API(rest);

-const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID!, commandData);
+const result = await api.applicationCommands.bulkOverwriteGlobalCommands(applicationId, commandData);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN!);
const api = new API(rest);
const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID!, commandData);
const token = process.env.DISCORD_TOKEN;
const applicationId = process.env.APPLICATION_ID;
if (!token) {
throw new Error('DISCORD_TOKEN environment variable is required');
}
if (!applicationId) {
throw new Error('APPLICATION_ID environment variable is required');
}
const rest = new REST({ version: '10' }).setToken(token);
const api = new API(rest);
const result = await api.applicationCommands.bulkOverwriteGlobalCommands(applicationId, commandData);
🤖 Prompt for AI Agents
In packages/create-discord-bot/template/Bun/TypeScript/src/util/deploy.ts around
lines 10 to 13, the code uses non-null assertions on process.env.DISCORD_TOKEN
and process.env.APPLICATION_ID which lead to cryptic runtime errors if those env
vars are missing; instead, read these values into well-named constants,
explicitly check each for presence at startup, and throw clear, descriptive
Errors (or log and exit) indicating which variable is missing and what value is
required before creating the REST/API instances and calling
bulkOverwriteGlobalCommands so failures surface with actionable messages.

Comment on lines +13 to +19
/**
* Loads all the structures in the provided directory
*
* @param dir - The directory to load the structures from
* @param predicate - The predicate to check if the structure is valid
* @param recursive - Whether to recursively load the structures in the directory
* @returns
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Minor: Incomplete JSDoc @returns tag.

The @returns tag on line 19 is missing its description.

  * @param dir - The directory to load the structures from
  * @param predicate - The predicate to check if the structure is valid
  * @param recursive - Whether to recursively load the structures in the directory
- * @returns
+ * @returns The loaded structures that satisfy the predicate
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Loads all the structures in the provided directory
*
* @param dir - The directory to load the structures from
* @param predicate - The predicate to check if the structure is valid
* @param recursive - Whether to recursively load the structures in the directory
* @returns
/**
* Loads all the structures in the provided directory
*
* @param dir - The directory to load the structures from
* @param predicate - The predicate to check if the structure is valid
* @param recursive - Whether to recursively load the structures in the directory
* @returns The loaded structures that satisfy the predicate
*/
🤖 Prompt for AI Agents
packages/create-discord-bot/template/Bun/TypeScript/src/util/loaders.ts around
lines 13 to 19: the JSDoc block for the function has an empty `@returns` tag;
update it to describe what the function returns (e.g., an array of loaded
structures or a Promise resolving to that array) and include the return
type/shape and any relevant detail about when it resolves/rejects so the
documentation is complete and accurate.

@vercel vercel bot temporarily deployed to Preview – discord-js December 9, 2025 14:47 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide December 9, 2025 14:47 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Implement Bun templates for create-discord-bot

1 participant