@minesa-org/mini-interaction 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/builders/ActionRowBuilder.d.ts +25 -0
  4. package/dist/builders/ActionRowBuilder.js +35 -0
  5. package/dist/builders/ButtonBuilder.d.ts +53 -0
  6. package/dist/builders/ButtonBuilder.js +124 -0
  7. package/dist/builders/ChannelSelectMenuBuilder.d.ts +58 -0
  8. package/dist/builders/ChannelSelectMenuBuilder.js +111 -0
  9. package/dist/builders/ModalBuilder.d.ts +40 -0
  10. package/dist/builders/ModalBuilder.js +65 -0
  11. package/dist/builders/RoleSelectMenuBuilder.d.ts +52 -0
  12. package/dist/builders/RoleSelectMenuBuilder.js +98 -0
  13. package/dist/builders/StringSelectMenuBuilder.d.ts +56 -0
  14. package/dist/builders/StringSelectMenuBuilder.js +100 -0
  15. package/dist/builders/index.d.ts +14 -0
  16. package/dist/builders/index.js +7 -0
  17. package/dist/builders/shared.d.ts +8 -0
  18. package/dist/builders/shared.js +11 -0
  19. package/dist/clients/MiniInteraction.d.ts +176 -0
  20. package/dist/clients/MiniInteraction.js +578 -0
  21. package/dist/commands/CommandBuilder.d.ts +278 -0
  22. package/dist/commands/CommandBuilder.js +687 -0
  23. package/dist/index.d.ts +16 -0
  24. package/dist/index.js +9 -0
  25. package/dist/types/ButtonStyle.d.ts +16 -0
  26. package/dist/types/ButtonStyle.js +17 -0
  27. package/dist/types/ChannelType.d.ts +2 -0
  28. package/dist/types/ChannelType.js +2 -0
  29. package/dist/types/Commands.d.ts +11 -0
  30. package/dist/types/Commands.js +1 -0
  31. package/dist/types/ComponentTypes.d.ts +5 -0
  32. package/dist/types/ComponentTypes.js +1 -0
  33. package/dist/types/InteractionFlags.d.ts +10 -0
  34. package/dist/types/InteractionFlags.js +12 -0
  35. package/dist/types/RoleConnectionMetadataTypes.d.ts +11 -0
  36. package/dist/types/RoleConnectionMetadataTypes.js +12 -0
  37. package/dist/utils/CommandInteractionOptions.d.ts +143 -0
  38. package/dist/utils/CommandInteractionOptions.js +376 -0
  39. package/dist/utils/MessageComponentInteraction.d.ts +19 -0
  40. package/dist/utils/MessageComponentInteraction.js +60 -0
  41. package/dist/utils/constants.d.ts +16 -0
  42. package/dist/utils/constants.js +16 -0
  43. package/dist/utils/interactionMessageHelpers.d.ts +30 -0
  44. package/dist/utils/interactionMessageHelpers.js +32 -0
  45. package/package.json +50 -0
@@ -0,0 +1,56 @@
1
+ import { type APISelectMenuOption, type APIStringSelectComponent } from "discord-api-types/v10";
2
+ import type { JSONEncodable } from "./shared.js";
3
+ /** Shape describing initial string select menu data accepted by the builder. */
4
+ export type StringSelectMenuBuilderData = {
5
+ customId?: string;
6
+ placeholder?: string;
7
+ minValues?: number;
8
+ maxValues?: number;
9
+ disabled?: boolean;
10
+ required?: boolean;
11
+ options?: APISelectMenuOption[];
12
+ };
13
+ /** Builder for Discord string select menu components. */
14
+ export declare class StringSelectMenuBuilder implements JSONEncodable<APIStringSelectComponent> {
15
+ private data;
16
+ /**
17
+ * Creates a new string select menu builder with optional seed data.
18
+ */
19
+ constructor(data?: StringSelectMenuBuilderData);
20
+ /**
21
+ * Sets the unique custom identifier for the select menu interaction.
22
+ */
23
+ setCustomId(customId: string): this;
24
+ /**
25
+ * Sets or clears the placeholder text displayed when no option is selected.
26
+ */
27
+ setPlaceholder(placeholder: string | null | undefined): this;
28
+ /**
29
+ * Sets the minimum number of options that must be selected.
30
+ */
31
+ setMinValues(minValues: number | null | undefined): this;
32
+ /**
33
+ * Sets the maximum number of options that can be selected.
34
+ */
35
+ setMaxValues(maxValues: number | null | undefined): this;
36
+ /**
37
+ * Toggles whether the select menu is disabled.
38
+ */
39
+ setDisabled(disabled: boolean): this;
40
+ /**
41
+ * Marks the select menu options as required.
42
+ */
43
+ setRequired(required: boolean): this;
44
+ /**
45
+ * Appends new option entries to the select menu.
46
+ */
47
+ addOptions(...options: APISelectMenuOption[]): this;
48
+ /**
49
+ * Replaces the current option set with the provided iterable.
50
+ */
51
+ setOptions(options: Iterable<APISelectMenuOption>): this;
52
+ /**
53
+ * Serialises the builder into an API compatible string select menu payload.
54
+ */
55
+ toJSON(): APIStringSelectComponent;
56
+ }
@@ -0,0 +1,100 @@
1
+ import { ComponentType, } from "discord-api-types/v10";
2
+ /** Builder for Discord string select menu components. */
3
+ export class StringSelectMenuBuilder {
4
+ data;
5
+ /**
6
+ * Creates a new string select menu builder with optional seed data.
7
+ */
8
+ constructor(data = {}) {
9
+ this.data = {
10
+ customId: data.customId,
11
+ placeholder: data.placeholder,
12
+ minValues: data.minValues,
13
+ maxValues: data.maxValues,
14
+ disabled: data.disabled,
15
+ required: data.required,
16
+ options: data.options ? [...data.options] : [],
17
+ };
18
+ }
19
+ /**
20
+ * Sets the unique custom identifier for the select menu interaction.
21
+ */
22
+ setCustomId(customId) {
23
+ this.data.customId = customId;
24
+ return this;
25
+ }
26
+ /**
27
+ * Sets or clears the placeholder text displayed when no option is selected.
28
+ */
29
+ setPlaceholder(placeholder) {
30
+ this.data.placeholder = placeholder ?? undefined;
31
+ return this;
32
+ }
33
+ /**
34
+ * Sets the minimum number of options that must be selected.
35
+ */
36
+ setMinValues(minValues) {
37
+ this.data.minValues = minValues ?? undefined;
38
+ return this;
39
+ }
40
+ /**
41
+ * Sets the maximum number of options that can be selected.
42
+ */
43
+ setMaxValues(maxValues) {
44
+ this.data.maxValues = maxValues ?? undefined;
45
+ return this;
46
+ }
47
+ /**
48
+ * Toggles whether the select menu is disabled.
49
+ */
50
+ setDisabled(disabled) {
51
+ this.data.disabled = disabled;
52
+ return this;
53
+ }
54
+ /**
55
+ * Marks the select menu options as required.
56
+ */
57
+ setRequired(required) {
58
+ this.data.required = required;
59
+ return this;
60
+ }
61
+ /**
62
+ * Appends new option entries to the select menu.
63
+ */
64
+ addOptions(...options) {
65
+ this.data.options.push(...options.map((option) => ({ ...option })));
66
+ return this;
67
+ }
68
+ /**
69
+ * Replaces the current option set with the provided iterable.
70
+ */
71
+ setOptions(options) {
72
+ this.data.options = Array.from(options, (option) => ({ ...option }));
73
+ return this;
74
+ }
75
+ /**
76
+ * Serialises the builder into an API compatible string select menu payload.
77
+ */
78
+ toJSON() {
79
+ const { customId, options } = this.data;
80
+ if (!customId) {
81
+ throw new Error("[StringSelectMenuBuilder] custom id is required.");
82
+ }
83
+ if (options.length === 0) {
84
+ throw new Error("[StringSelectMenuBuilder] at least one option is required.");
85
+ }
86
+ if (options.length > 25) {
87
+ throw new Error("[StringSelectMenuBuilder] no more than 25 options can be provided.");
88
+ }
89
+ return {
90
+ type: ComponentType.StringSelect,
91
+ custom_id: customId,
92
+ placeholder: this.data.placeholder,
93
+ min_values: this.data.minValues,
94
+ max_values: this.data.maxValues,
95
+ disabled: this.data.disabled,
96
+ required: this.data.required,
97
+ options: options.map((option) => ({ ...option })),
98
+ };
99
+ }
100
+ }
@@ -0,0 +1,14 @@
1
+ /** Re-exports component builders and shared types for convenience. */
2
+ export { ActionRowBuilder } from "./ActionRowBuilder.js";
3
+ export type { ActionRowComponentLike } from "./ActionRowBuilder.js";
4
+ export { ButtonBuilder } from "./ButtonBuilder.js";
5
+ export type { ButtonBuilderData } from "./ButtonBuilder.js";
6
+ export { StringSelectMenuBuilder } from "./StringSelectMenuBuilder.js";
7
+ export type { StringSelectMenuBuilderData } from "./StringSelectMenuBuilder.js";
8
+ export { RoleSelectMenuBuilder } from "./RoleSelectMenuBuilder.js";
9
+ export type { RoleSelectMenuBuilderData } from "./RoleSelectMenuBuilder.js";
10
+ export { ChannelSelectMenuBuilder } from "./ChannelSelectMenuBuilder.js";
11
+ export type { ChannelSelectMenuBuilderData } from "./ChannelSelectMenuBuilder.js";
12
+ export { ModalBuilder } from "./ModalBuilder.js";
13
+ export type { ModalBuilderData, ModalComponentLike } from "./ModalBuilder.js";
14
+ export type { JSONEncodable } from "./shared.js";
@@ -0,0 +1,7 @@
1
+ /** Re-exports component builders and shared types for convenience. */
2
+ export { ActionRowBuilder } from "./ActionRowBuilder.js";
3
+ export { ButtonBuilder } from "./ButtonBuilder.js";
4
+ export { StringSelectMenuBuilder } from "./StringSelectMenuBuilder.js";
5
+ export { RoleSelectMenuBuilder } from "./RoleSelectMenuBuilder.js";
6
+ export { ChannelSelectMenuBuilder } from "./ChannelSelectMenuBuilder.js";
7
+ export { ModalBuilder } from "./ModalBuilder.js";
@@ -0,0 +1,8 @@
1
+ /** Interface describing objects capable of encoding themselves as JSON payloads. */
2
+ export interface JSONEncodable<T> {
3
+ toJSON(): T;
4
+ }
5
+ /** Type guard that checks whether a value provides a `toJSON` method. */
6
+ export declare function isJSONEncodable<T>(value: JSONEncodable<T> | unknown): value is JSONEncodable<T>;
7
+ /** Normalises a value that might either be a JSON encodable object or plain payload. */
8
+ export declare function resolveJSONEncodable<T>(value: JSONEncodable<T> | T): T;
@@ -0,0 +1,11 @@
1
+ /** Type guard that checks whether a value provides a `toJSON` method. */
2
+ export function isJSONEncodable(value) {
3
+ return (typeof value === "object" &&
4
+ value !== null &&
5
+ "toJSON" in value &&
6
+ typeof value.toJSON === "function");
7
+ }
8
+ /** Normalises a value that might either be a JSON encodable object or plain payload. */
9
+ export function resolveJSONEncodable(value) {
10
+ return isJSONEncodable(value) ? value.toJSON() : value;
11
+ }
@@ -0,0 +1,176 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import { APIInteractionResponse, RESTPostAPIChatInputApplicationCommandsJSONBody } from "discord-api-types/v10";
3
+ import type { MiniInteractionCommand } from "../types/Commands.js";
4
+ import { RoleConnectionMetadataTypes } from "../types/RoleConnectionMetadataTypes.js";
5
+ import { type MessageComponentInteraction } from "../utils/MessageComponentInteraction.js";
6
+ /** Configuration parameters for the MiniInteraction client. */
7
+ export type MiniInteractionOptions = {
8
+ applicationId: string;
9
+ publicKey: string;
10
+ commandsDirectory?: string | false;
11
+ fetchImplementation?: typeof fetch;
12
+ verifyKeyImplementation?: VerifyKeyFunction;
13
+ };
14
+ /** Payload structure for role connection metadata registration. */
15
+ export type RoleConnectionMetadataField = {
16
+ key: string;
17
+ name: string;
18
+ description: string;
19
+ type: RoleConnectionMetadataTypes;
20
+ };
21
+ /**
22
+ * HTTP request information needed to validate and handle Discord interaction payloads.
23
+ */
24
+ export type MiniInteractionRequest = {
25
+ body: string | Uint8Array;
26
+ signature?: string;
27
+ timestamp?: string;
28
+ };
29
+ /** Result payload returned by request handlers when processing an interaction. */
30
+ export type MiniInteractionHandlerResult = {
31
+ status: number;
32
+ body: APIInteractionResponse | {
33
+ error: string;
34
+ };
35
+ };
36
+ /** Handler signature invoked for Discord message component interactions. */
37
+ export type MiniInteractionComponentHandler = (interaction: MessageComponentInteraction) => Promise<APIInteractionResponse | void> | APIInteractionResponse | void;
38
+ /** Structure describing a component handler mapped to a custom id. */
39
+ export type MiniInteractionComponent = {
40
+ customId: string;
41
+ handler: MiniInteractionComponentHandler;
42
+ };
43
+ /** Node.js HTTP handler compatible with frameworks like Express or Next.js API routes. */
44
+ export type MiniInteractionNodeHandler = (request: IncomingMessage, response: ServerResponse) => void;
45
+ /** Web Fetch API compatible request handler for platforms such as Cloudflare Workers. */
46
+ export type MiniInteractionFetchHandler = (request: Request) => Promise<Response>;
47
+ /**
48
+ * Minimal interface describing a function capable of verifying Discord interaction signatures.
49
+ */
50
+ type VerifyKeyFunction = (message: string | Uint8Array, signature: string, timestamp: string, publicKey: string) => boolean | Promise<boolean>;
51
+ /**
52
+ * Lightweight client for registering, loading, and handling Discord slash command interactions.
53
+ */
54
+ export declare class MiniInteraction {
55
+ readonly applicationId: string;
56
+ readonly publicKey: string;
57
+ private readonly baseUrl;
58
+ private readonly fetchImpl;
59
+ private readonly verifyKeyImpl;
60
+ private readonly commandsDirectory;
61
+ private readonly commands;
62
+ private readonly componentHandlers;
63
+ private commandsLoaded;
64
+ private loadCommandsPromise;
65
+ /**
66
+ * Creates a new MiniInteraction client with optional command auto-loading and custom runtime hooks.
67
+ */
68
+ constructor({ applicationId, publicKey, commandsDirectory, fetchImplementation, verifyKeyImplementation, }: MiniInteractionOptions);
69
+ /**
70
+ * Registers a single command handler with the client.
71
+ *
72
+ * @param command - The command definition to register.
73
+ */
74
+ useCommand(command: MiniInteractionCommand): this;
75
+ /**
76
+ * Registers multiple command handlers with the client.
77
+ *
78
+ * @param commands - The command definitions to register.
79
+ */
80
+ useCommands(commands: MiniInteractionCommand[]): this;
81
+ /**
82
+ * Registers a single component handler mapped to a custom identifier.
83
+ *
84
+ * @param component - The component definition to register.
85
+ */
86
+ useComponent(component: MiniInteractionComponent): this;
87
+ /**
88
+ * Registers multiple component handlers in a single call.
89
+ *
90
+ * @param components - The component definitions to register.
91
+ */
92
+ useComponents(components: MiniInteractionComponent[]): this;
93
+ /**
94
+ * Recursively loads commands from the configured commands directory.
95
+ *
96
+ * @param directory - Optional directory override for command discovery.
97
+ */
98
+ loadCommandsFromDirectory(directory?: string): Promise<this>;
99
+ /**
100
+ * Lists the raw command data payloads for registration with Discord.
101
+ */
102
+ listCommandData(): RESTPostAPIChatInputApplicationCommandsJSONBody[];
103
+ /**
104
+ * Registers slash commands with Discord's REST API.
105
+ *
106
+ * @param botToken - The bot token authorising the registration request.
107
+ * @param commands - Optional command list to register instead of auto-loaded commands.
108
+ */
109
+ registerCommands(botToken: string, commands?: RESTPostAPIChatInputApplicationCommandsJSONBody[]): Promise<unknown>;
110
+ /**
111
+ * Registers role connection metadata with Discord's REST API.
112
+ *
113
+ * @param botToken - The bot token authorising the request.
114
+ * @param metadata - The metadata collection to register.
115
+ */
116
+ registerMetadata(botToken: string, metadata: RoleConnectionMetadataField[]): Promise<unknown>;
117
+ /**
118
+ * Validates and handles a single Discord interaction request.
119
+ *
120
+ * @param request - The request payload containing headers and body data.
121
+ */
122
+ handleRequest(request: MiniInteractionRequest): Promise<MiniInteractionHandlerResult>;
123
+ /**
124
+ * Creates a Node.js style request handler that validates and processes interactions.
125
+ */
126
+ createNodeHandler(): MiniInteractionNodeHandler;
127
+ /**
128
+ * Alias for {@link createNodeHandler} for frameworks expecting a listener function.
129
+ */
130
+ createNodeListener(): MiniInteractionNodeHandler;
131
+ /**
132
+ * Convenience alias for {@link createNodeHandler} tailored to Vercel serverless functions.
133
+ */
134
+ createVercelHandler(): MiniInteractionNodeHandler;
135
+ /**
136
+ * Creates a Fetch API compatible handler for runtimes like Workers or Deno.
137
+ */
138
+ createFetchHandler(): MiniInteractionFetchHandler;
139
+ /**
140
+ * Checks if the provided directory path exists on disk.
141
+ */
142
+ private pathExists;
143
+ /**
144
+ * Recursively collects all command module file paths from the target directory.
145
+ */
146
+ private collectCommandFiles;
147
+ /**
148
+ * Determines whether the provided file path matches a supported command file extension.
149
+ */
150
+ private isSupportedCommandFile;
151
+ /**
152
+ * Dynamically imports and validates a command module from disk.
153
+ */
154
+ private importCommandModule;
155
+ /**
156
+ * Normalises the request body into a UTF-8 string for signature validation and parsing.
157
+ */
158
+ private normalizeBody;
159
+ /**
160
+ * Ensures commands have been loaded from disk once before being accessed.
161
+ */
162
+ private ensureCommandsLoaded;
163
+ /**
164
+ * Resolves the absolute commands directory path from configuration.
165
+ */
166
+ private resolveCommandsDirectory;
167
+ /**
168
+ * Handles execution of a message component interaction.
169
+ */
170
+ private handleMessageComponent;
171
+ /**
172
+ * Handles execution of an application command interaction.
173
+ */
174
+ private handleApplicationCommand;
175
+ }
176
+ export {};