@@ -6,7 +6,6 @@ import HttpInteractionServer from "./interactionServer.js";
66import InteractionRouterManger from "./interactionRouter/internal.js" ;
77import AutoCompleteKeyBuilder from "./interactionRouter/autoCompleteKeyBuilder.js" ;
88
9-
109import type { HttpAdapter , HttpAdapterSererResponse } from "./adapter/index.js" ;
1110
1211import {
@@ -34,36 +33,131 @@ import type {
3433 CommandbuilderType ,
3534} from "./interactionRouter/internal.js" ;
3635
36+ import type { MessageMentionOptions } from "discord.js" ;
37+
3738export interface ClientOptions {
3839 token : string ;
3940 publicKey : string ;
4041 httpAdapter : HttpAdapter ;
4142 debug ?: boolean ;
4243}
4344
45+ /**
46+ * Discord HTTPS Interaction Client.
47+ *
48+ * Handles registration of commands, buttons, modals, select menus, context menus,
49+ * and autocomplete interactions with their associated middleware.
50+ *
51+ * Also exposes a {@link REST} client for direct API calls.
52+ *
53+ * @example
54+ * ```ts
55+ * import Client from "./Client.js";
56+ * import NodeAdapter from "@discordhttps/nodejs-adapter";
57+ *
58+ * const client = new Client({
59+ * token: process.env.BOT_TOKEN!,
60+ * publicKey: process.env.PUBLIC_KEY!,
61+ * httpAdapter: new NodeAdapter(),
62+ * });
63+ *
64+ * client.command(
65+ * (builder) => builder.setName("ping").setDescription("Replies with Pong!"),
66+ * async (interaction, client, _, res) => {
67+ * res.writeHead(200, {
68+ * "Content-Type": "application/json",
69+ * });
70+ * const username = interaction.user
71+ * ? interaction.user.global_name
72+ * : interaction.member.user.global_name;
73+ * res.end(
74+ * JSON.stringify({
75+ * type: InteractionResponseType.ChannelMessageWithSource,
76+ * data: {
77+ * content: `Hello! ${username}`,
78+ * },
79+ * })
80+ * );
81+ * }
82+ * );
83+ *
84+ * await client.listen("interactions", 3000, () => {
85+ * console.log(
86+ * "Listening for interactions on port 3000 at the /interactions endpoint"
87+ * );
88+ * });
89+ * ```
90+ */
91+
4492class Client extends HttpInteractionServer {
93+ /** Interaction router manager responsible for routing incoming interactions. */
4594 private router = new InteractionRouterManger ( ) ;
46- client = new REST ( {
47- version : "10" ,
48- } ) ;
95+
96+ /**
97+ * REST API client instance used for interacting with Discord's HTTP API.
98+ *
99+ * @see {@link https://discord.js.org/docs/packages/rest/main | REST Documentation }
100+ */
101+ readonly rest ! : REST ;
102+
103+ /**
104+ * Creates a new Discord HTTPS Interaction Client.
105+ *
106+ * @param options - Client configuration options.
107+ * @param options.token - Discord bot token.
108+ * @param options.publicKey - Discord public key for interaction verification.
109+ * @param options.httpAdapter - HTTP adapter to handle incoming requests.
110+ * @param options.debug - Optional. Enable debug logging. Defaults to `false`.
111+ */
49112
50113 constructor ( { httpAdapter, publicKey, token, debug = false } : ClientOptions ) {
51114 super ( publicKey , httpAdapter , debug ) ;
52- this . client . setToken ( token ) ;
115+ Object . defineProperty ( this , "rest" , {
116+ value : new REST ( {
117+ version : "10" ,
118+ } ) ,
119+ } ) ;
120+ this . rest . setToken ( token ) ;
53121 }
54122
123+ /**
124+ * Registers interaction routes.
125+ *
126+ * @param routes - {@link InteractionRouter} or {@link InteractionRouterCollector} instances.
127+ */
128+
55129 register ( ...routes : Array < InteractionRouter | InteractionRouterCollector > ) {
56130 this . router . register ( ...routes ) ;
57131 }
58132
133+ /**
134+ * Adds global middleware that runs on every interaction.
135+ *
136+ * Receives raw {@link APIInteraction} payload and response object.
137+ *
138+ * @param fns - Middleware functions to execute.
139+ */
140+
59141 middleware ( ...fns : GeneralMiddleware [ ] ) {
60142 this . router . middlewares . push ( ...fns ) ;
61143 }
62144
145+ /**
146+ * Adds global middleware for unknown interactions.
147+ *
148+ * @param fns - Functions executed when no handler matches an interaction.
149+ */
63150 unknown ( ...fns : UnknownMiddleware [ ] ) {
64151 this . router . _unknownInteraction . push ( ...fns ) ;
65152 }
66153
154+ /**
155+ * Ensures all middleware functions are async.
156+ *
157+ * @internal
158+ * @param fns - Functions to check.
159+ * @throws If any function is not async.
160+ */
67161 tryAsync ( fns : Function [ ] ) {
68162 fns . forEach ( ( fn ) => {
69163 if ( fn . constructor . name !== "AsyncFunction" )
@@ -82,9 +176,13 @@ class Client extends HttpInteractionServer {
82176 * ```ts
83177 * router.command(
84178 * (builder) => builder.setName("Ping!").setDescription("Returns Pong!"),
85- * (interaction) => interaction.reply({ content: "pong!" })
179+ * async (interaction) => interaction.reply({ content: "pong!" })
86180 * );
87181 * ```
182+ *
183+ * @param commandbuilder - Function returning a {@link SlashCommandBuilder}.
184+ * @param fns - Middleware functions for the command.
185+ * @returns An {@link AutoCompleteKeyBuilder} for autocomplete options.
88186 */
89187 command ( commandbuilder : CommandbuilderType , ...fns : CommandMiddleware [ ] ) {
90188 this . tryAsync ( fns ) ;
@@ -197,7 +295,7 @@ class Client extends HttpInteractionServer {
197295 * (builder) =>
198296 * builder
199297 * .setName("weather") // The command name
200- * .setDescription("QuQuery weather information!") // The command description
298+ * .setDescription("Query weather information!") // The command description
201299 * .addStringOption(option =>
202300 * option
203301 * .setName("city") // Option name
@@ -224,6 +322,7 @@ class Client extends HttpInteractionServer {
224322 fns
225323 ) ;
226324 }
325+
227326 /**
228327 * Registers a user context menu interaction with its associated middleware.
229328 *
@@ -249,11 +348,13 @@ class Client extends HttpInteractionServer {
249348 this . tryAsync ( fns ) ;
250349 this . router . _register ( "messageContextMenu" , customId , fns ) ;
251350 }
252-
253- // protected httpInteractionPayloadHandler(
254- // body: APIInteraction,
255- // res: HttpAdapterSererResponse
256- // ) {
351+ /**
352+ * Handles incoming interaction payloads from Discord.
353+ *
354+ * @internal
355+ * @param body - The raw {@link APIInteraction} payload.
356+ * @param res - HTTP response object to reply to Discord.
357+ */
257358 protected async httpInteractionPayloadHandler (
258359 body : APIInteraction ,
259360 res : HttpAdapterSererResponse
@@ -271,13 +372,20 @@ class Client extends HttpInteractionServer {
271372 }
272373 this . debug ( "Interaction Request Received" ) ;
273374 // this.router.__internal_dispatch(res, body, this.client);
274- await this . router . __internal_dispatch ( res , body , this . client ) ;
375+ await this . router . __internal_dispatch ( res , body , this . rest ) ;
275376 }
377+
378+ /**
379+ * Returns helpers for registering slash commands.
380+ *
381+ * @param log - Log progress. Defaults to true.
382+ * @returns Methods to register commands globally or locally.
383+ */
276384 async getRegistar ( log = true ) {
277385 const commandsBody = this . router . CommandDefinitions ;
278386 var currentClient : APIApplication ;
279387 try {
280- currentClient = ( await this . client . get (
388+ currentClient = ( await this . rest . get (
281389 Routes . currentApplication ( )
282390 ) ) as APIApplication ;
283391 } catch ( e ) {
@@ -317,7 +425,7 @@ class Client extends HttpInteractionServer {
317425 }
318426
319427 try {
320- await upperThis . client . put (
428+ await upperThis . rest . put (
321429 Routes . applicationCommands ( currentClient . id ) ,
322430 { body : commandsBody }
323431 ) ;
@@ -357,7 +465,7 @@ class Client extends HttpInteractionServer {
357465 }
358466
359467 try {
360- await upperThis . client . put (
468+ await upperThis . rest . put (
361469 Routes . applicationGuildCommands ( currentClient . id , guildId ) ,
362470 { body : commandsBody }
363471 ) ;
@@ -385,3 +493,5 @@ class Client extends HttpInteractionServer {
385493}
386494
387495export default Client ;
496+ export * from "@discordjs/builders" ;
497+ export * from "discord-api-types/v10" ;
0 commit comments