@minesa-org/mini-interaction 0.3.14 → 0.4.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.
- package/README.md +143 -2
- package/dist/builders/FileUploadBuilder.d.ts +3 -23
- package/dist/builders/FileUploadBuilder.js +16 -53
- package/dist/builders/LabelBuilder.d.ts +3 -22
- package/dist/builders/LabelBuilder.js +16 -50
- package/dist/builders/ModalBuilder.d.ts +4 -28
- package/dist/builders/ModalBuilder.js +20 -81
- package/dist/builders/ModalChannelSelectMenuBuilder.d.ts +7 -43
- package/dist/builders/ModalChannelSelectMenuBuilder.js +22 -107
- package/dist/builders/ModalRoleSelectMenuBuilder.d.ts +6 -35
- package/dist/builders/ModalRoleSelectMenuBuilder.js +21 -90
- package/dist/builders/RadioBuilder.d.ts +17 -0
- package/dist/builders/RadioBuilder.js +29 -0
- package/dist/builders/TextInputBuilder.d.ts +3 -32
- package/dist/builders/TextInputBuilder.js +21 -83
- package/dist/builders/__tests__/builders.test.d.ts +1 -0
- package/dist/builders/__tests__/builders.test.js +31 -0
- package/dist/builders/index.d.ts +2 -0
- package/dist/builders/index.js +1 -0
- package/dist/core/http/DiscordRestClient.d.ts +19 -0
- package/dist/core/http/DiscordRestClient.js +55 -0
- package/dist/core/interactions/InteractionContext.d.ts +25 -0
- package/dist/core/interactions/InteractionContext.js +44 -0
- package/dist/core/interactions/InteractionVerifier.d.ts +8 -0
- package/dist/core/interactions/InteractionVerifier.js +9 -0
- package/dist/core/interactions/__tests__/interaction-context.test.d.ts +1 -0
- package/dist/core/interactions/__tests__/interaction-context.test.js +38 -0
- package/dist/index.d.ts +10 -6
- package/dist/index.js +8 -3
- package/dist/router/InteractionRouter.d.ts +12 -0
- package/dist/router/InteractionRouter.js +33 -0
- package/dist/types/InteractionFlags.d.ts +0 -4
- package/dist/types/InteractionFlags.js +0 -4
- package/dist/types/discord.d.ts +11 -0
- package/dist/types/discord.js +1 -0
- package/dist/types/radio.d.ts +23 -0
- package/dist/types/radio.js +5 -0
- package/dist/types/validation.d.ts +8 -0
- package/dist/types/validation.js +26 -0
- package/dist/utils/ModalSubmitInteraction.js +5 -2
- package/package.json +55 -53
- package/dist/clients/MiniInteraction.d.ts +0 -441
- package/dist/clients/MiniInteraction.js +0 -1731
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { APIInteractionResponse, APIInteractionResponseCallbackData, APIModalInteractionResponseCallbackData } from 'discord-api-types/v10';
|
|
2
|
+
import type { ParsedInteraction } from '../../types/discord.js';
|
|
3
|
+
import { DiscordRestClient } from '../http/DiscordRestClient.js';
|
|
4
|
+
export type InteractionContextOptions = {
|
|
5
|
+
interaction: ParsedInteraction;
|
|
6
|
+
rest: DiscordRestClient;
|
|
7
|
+
autoAck?: {
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
delayMs?: number;
|
|
10
|
+
};
|
|
11
|
+
onDiagnostic?: (message: string) => void;
|
|
12
|
+
};
|
|
13
|
+
export declare class InteractionContext {
|
|
14
|
+
private readonly options;
|
|
15
|
+
private responded;
|
|
16
|
+
private autoAckTimer?;
|
|
17
|
+
constructor(options: InteractionContextOptions);
|
|
18
|
+
reply(data: APIInteractionResponseCallbackData): APIInteractionResponse;
|
|
19
|
+
deferReply(ephemeral?: boolean): APIInteractionResponse;
|
|
20
|
+
showModal(data: APIModalInteractionResponseCallbackData): APIInteractionResponse;
|
|
21
|
+
editReply(body: unknown): Promise<unknown>;
|
|
22
|
+
followUp(body: unknown): Promise<unknown>;
|
|
23
|
+
get hasResponded(): boolean;
|
|
24
|
+
private clearAutoAck;
|
|
25
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export class InteractionContext {
|
|
2
|
+
options;
|
|
3
|
+
responded = false;
|
|
4
|
+
autoAckTimer;
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
if (options.autoAck?.enabled) {
|
|
8
|
+
const delay = options.autoAck.delayMs ?? 2000;
|
|
9
|
+
this.autoAckTimer = setTimeout(() => {
|
|
10
|
+
if (!this.responded) {
|
|
11
|
+
options.onDiagnostic?.(`[InteractionContext] auto-ack triggered for ${this.options.interaction.id}`);
|
|
12
|
+
}
|
|
13
|
+
}, delay);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
reply(data) {
|
|
17
|
+
this.responded = true;
|
|
18
|
+
this.clearAutoAck();
|
|
19
|
+
return { type: 4, data };
|
|
20
|
+
}
|
|
21
|
+
deferReply(ephemeral = false) {
|
|
22
|
+
this.responded = true;
|
|
23
|
+
this.clearAutoAck();
|
|
24
|
+
return { type: 5, data: ephemeral ? { flags: 64 } : undefined };
|
|
25
|
+
}
|
|
26
|
+
showModal(data) {
|
|
27
|
+
this.responded = true;
|
|
28
|
+
this.clearAutoAck();
|
|
29
|
+
return { type: 9, data };
|
|
30
|
+
}
|
|
31
|
+
editReply(body) {
|
|
32
|
+
return this.options.rest.editOriginal(this.options.interaction.token, body);
|
|
33
|
+
}
|
|
34
|
+
followUp(body) {
|
|
35
|
+
return this.options.rest.createFollowup(this.options.interaction.token, body);
|
|
36
|
+
}
|
|
37
|
+
get hasResponded() {
|
|
38
|
+
return this.responded;
|
|
39
|
+
}
|
|
40
|
+
clearAutoAck() {
|
|
41
|
+
if (this.autoAckTimer)
|
|
42
|
+
clearTimeout(this.autoAckTimer);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { APIInteraction } from 'discord-api-types/v10';
|
|
2
|
+
export type VerifyInteractionRequest = {
|
|
3
|
+
body: string | Uint8Array;
|
|
4
|
+
signature: string;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
publicKey: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function verifyAndParseInteraction(request: VerifyInteractionRequest): Promise<APIInteraction>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { verifyKey } from 'discord-interactions';
|
|
2
|
+
export async function verifyAndParseInteraction(request) {
|
|
3
|
+
const valid = await verifyKey(request.body, request.signature, request.timestamp, request.publicKey);
|
|
4
|
+
if (!valid) {
|
|
5
|
+
throw new Error('[InteractionVerifier] invalid interaction signature');
|
|
6
|
+
}
|
|
7
|
+
const bodyText = typeof request.body === 'string' ? request.body : Buffer.from(request.body).toString('utf8');
|
|
8
|
+
return JSON.parse(bodyText);
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { InteractionContext } from '../InteractionContext.js';
|
|
4
|
+
import { DiscordRestClient } from '../../http/DiscordRestClient.js';
|
|
5
|
+
function createRest() {
|
|
6
|
+
const calls = [];
|
|
7
|
+
const fetchImpl = (async (input) => {
|
|
8
|
+
calls.push(String(input));
|
|
9
|
+
return new Response(JSON.stringify({ ok: true }), { status: 200 });
|
|
10
|
+
});
|
|
11
|
+
return {
|
|
12
|
+
calls,
|
|
13
|
+
rest: new DiscordRestClient({ token: 'x', applicationId: 'app', fetchImplementation: fetchImpl }),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const interaction = { id: '1', application_id: 'a', type: 2, token: 'tok', version: 1 };
|
|
17
|
+
test('reply/defer lifecycle', () => {
|
|
18
|
+
const { rest } = createRest();
|
|
19
|
+
const ctx = new InteractionContext({ interaction, rest });
|
|
20
|
+
const response = ctx.reply({ content: 'ok' });
|
|
21
|
+
assert.equal(response.type, 4);
|
|
22
|
+
assert.equal(ctx.hasResponded, true);
|
|
23
|
+
});
|
|
24
|
+
test('editReply and followUp call webhook endpoints', async () => {
|
|
25
|
+
const { rest, calls } = createRest();
|
|
26
|
+
const ctx = new InteractionContext({ interaction, rest });
|
|
27
|
+
await ctx.editReply({ content: 'edit' });
|
|
28
|
+
await ctx.followUp({ content: 'next' });
|
|
29
|
+
assert.equal(calls.length, 2);
|
|
30
|
+
assert.match(calls[0], /messages\/\@original/);
|
|
31
|
+
});
|
|
32
|
+
test('auto-ack diagnostics callback fires for slow handler', async () => {
|
|
33
|
+
let message = '';
|
|
34
|
+
const { rest } = createRest();
|
|
35
|
+
new InteractionContext({ interaction, rest, autoAck: { enabled: true, delayMs: 5 }, onDiagnostic: (m) => (message = m) });
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
37
|
+
assert.match(message, /auto-ack triggered/);
|
|
38
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
/** Entry point re-exporting MiniInteraction helpers, builders, and shared types. */
|
|
2
|
-
export { MiniInteraction } from "./clients/MiniInteraction.js";
|
|
3
|
-
export type { RoleConnectionMetadataField } from "./clients/MiniInteraction.js";
|
|
4
1
|
export { CommandBuilder, CommandContext, IntegrationType, } from "./commands/CommandBuilder.js";
|
|
5
2
|
export { UserCommandBuilder, MessageCommandBuilder, AppCommandBuilder, } from "./commands/ContextMenuCommandBuilder.js";
|
|
6
3
|
export type { AttachmentOptionBuilder, ChannelOptionBuilder, MentionableOptionBuilder, NumberOptionBuilder, RoleOptionBuilder, StringOptionBuilder, SubcommandBuilder, SubcommandGroupBuilder, UserOptionBuilder, } from "./commands/CommandBuilder.js";
|
|
7
4
|
export { CommandInteractionOptionResolver, createCommandInteraction, } from "./utils/CommandInteractionOptions.js";
|
|
8
5
|
export { CommandInteraction, MentionableOption, ResolvedUserOption, } from "./utils/CommandInteractionOptions.js";
|
|
9
6
|
export { UserContextMenuInteraction, MessageContextMenuInteraction, AppCommandInteraction, } from "./utils/ContextMenuInteraction.js";
|
|
10
|
-
export type { InteractionFetchHandler, InteractionNodeHandler, InteractionHandlerResult, InteractionRequest, InteractionClientOptions, DiscordOAuthAuthorizeContext, DiscordOAuthCallbackOptions, DiscordOAuthCallbackTemplates, DiscordOAuthErrorTemplateContext, DiscordOAuthServerErrorTemplateContext, DiscordOAuthStateTemplateContext, DiscordOAuthSuccessTemplateContext, DiscordOAuthVerificationPageOptions, } from "./clients/MiniInteraction.js";
|
|
11
7
|
export type { InteractionCommand, SlashCommandHandler, UserCommandHandler, MessageCommandHandler, AppCommandHandler, CommandHandler, } from "./types/Commands.js";
|
|
12
|
-
export type { ComponentCommand, ButtonComponentHandler, StringSelectComponentHandler, RoleSelectComponentHandler, UserSelectComponentHandler, ChannelSelectComponentHandler, MentionableSelectComponentHandler, ComponentHandler, ModalCommand, ModalHandler, InteractionHandler, } from "./clients/MiniInteraction.js";
|
|
13
8
|
export { MessageComponentInteraction, ButtonInteraction, StringSelectInteraction, RoleSelectInteraction, UserSelectInteraction, ChannelSelectInteraction, MentionableSelectInteraction, ResolvedUserOption as ComponentResolvedUserOption, ResolvedMentionableOption as ComponentResolvedMentionableOption, } from "./utils/MessageComponentInteraction.js";
|
|
14
9
|
export { ModalSubmitInteraction } from "./utils/ModalSubmitInteraction.js";
|
|
15
10
|
export { RoleConnectionMetadataTypes } from "./types/RoleConnectionMetadataTypes.js";
|
|
16
11
|
export { ChannelType } from "./types/ChannelType.js";
|
|
17
|
-
export {
|
|
12
|
+
export { InteractionFlags, } from "./types/InteractionFlags.js";
|
|
18
13
|
export { ButtonStyle } from "./types/ButtonStyle.js";
|
|
19
14
|
export { SeparatorSpacingSize } from "./types/SeparatorSpacingSize.js";
|
|
20
15
|
export { TextInputStyle } from "discord-api-types/v10";
|
|
@@ -29,3 +24,12 @@ export { MiniDatabase } from "./database/MiniDatabase.js";
|
|
|
29
24
|
export { generateOAuthUrl, getOAuthTokens, refreshAccessToken, getDiscordUser, ensureValidToken, } from "./oauth/DiscordOAuth.js";
|
|
30
25
|
export type { OAuthConfig, OAuthTokens, DiscordUser, } from "./oauth/DiscordOAuth.js";
|
|
31
26
|
export { OAuthTokenStorage } from "./oauth/OAuthTokenStorage.js";
|
|
27
|
+
export { DiscordRestClient } from "./core/http/DiscordRestClient.js";
|
|
28
|
+
export type { DiscordRestClientOptions } from "./core/http/DiscordRestClient.js";
|
|
29
|
+
export { InteractionContext } from "./core/interactions/InteractionContext.js";
|
|
30
|
+
export type { InteractionContextOptions } from "./core/interactions/InteractionContext.js";
|
|
31
|
+
export { verifyAndParseInteraction } from "./core/interactions/InteractionVerifier.js";
|
|
32
|
+
export { InteractionRouter } from "./router/InteractionRouter.js";
|
|
33
|
+
export type { APIRadioComponent, APIRadioOption } from "./types/radio.js";
|
|
34
|
+
export { RADIO_COMPONENT_TYPE } from "./types/radio.js";
|
|
35
|
+
export { ValidationError } from "./types/validation.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** Entry point re-exporting MiniInteraction helpers, builders, and shared types. */
|
|
2
|
-
export { MiniInteraction } from "./clients/MiniInteraction.js";
|
|
3
1
|
export { CommandBuilder, CommandContext, IntegrationType, } from "./commands/CommandBuilder.js";
|
|
4
2
|
export { UserCommandBuilder, MessageCommandBuilder, AppCommandBuilder, } from "./commands/ContextMenuCommandBuilder.js";
|
|
5
3
|
export { CommandInteractionOptionResolver, createCommandInteraction, } from "./utils/CommandInteractionOptions.js";
|
|
@@ -9,7 +7,7 @@ export { MessageComponentInteraction, ButtonInteraction, StringSelectInteraction
|
|
|
9
7
|
export { ModalSubmitInteraction } from "./utils/ModalSubmitInteraction.js";
|
|
10
8
|
export { RoleConnectionMetadataTypes } from "./types/RoleConnectionMetadataTypes.js";
|
|
11
9
|
export { ChannelType } from "./types/ChannelType.js";
|
|
12
|
-
export {
|
|
10
|
+
export { InteractionFlags, } from "./types/InteractionFlags.js";
|
|
13
11
|
export { ButtonStyle } from "./types/ButtonStyle.js";
|
|
14
12
|
export { SeparatorSpacingSize } from "./types/SeparatorSpacingSize.js";
|
|
15
13
|
export { TextInputStyle } from "discord-api-types/v10";
|
|
@@ -20,3 +18,10 @@ export { MiniDatabaseBuilder } from "./database/MiniDatabaseBuilder.js";
|
|
|
20
18
|
export { MiniDatabase } from "./database/MiniDatabase.js";
|
|
21
19
|
export { generateOAuthUrl, getOAuthTokens, refreshAccessToken, getDiscordUser, ensureValidToken, } from "./oauth/DiscordOAuth.js";
|
|
22
20
|
export { OAuthTokenStorage } from "./oauth/OAuthTokenStorage.js";
|
|
21
|
+
// New v10 core modules
|
|
22
|
+
export { DiscordRestClient } from "./core/http/DiscordRestClient.js";
|
|
23
|
+
export { InteractionContext } from "./core/interactions/InteractionContext.js";
|
|
24
|
+
export { verifyAndParseInteraction } from "./core/interactions/InteractionVerifier.js";
|
|
25
|
+
export { InteractionRouter } from "./router/InteractionRouter.js";
|
|
26
|
+
export { RADIO_COMPONENT_TYPE } from "./types/radio.js";
|
|
27
|
+
export { ValidationError } from "./types/validation.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { APIInteraction, APIInteractionResponse, APIMessageComponentInteraction, APIModalSubmitInteraction, APIChatInputApplicationCommandInteraction } from 'discord-api-types/v10';
|
|
2
|
+
import { InteractionContext } from '../core/interactions/InteractionContext.js';
|
|
3
|
+
export type RouterHandler<T extends APIInteraction> = (interaction: T, ctx: InteractionContext) => Promise<APIInteractionResponse | void> | APIInteractionResponse | void;
|
|
4
|
+
export declare class InteractionRouter {
|
|
5
|
+
private readonly commandHandlers;
|
|
6
|
+
private readonly componentHandlers;
|
|
7
|
+
private readonly modalHandlers;
|
|
8
|
+
onCommand(name: string, handler: RouterHandler<APIChatInputApplicationCommandInteraction>): this;
|
|
9
|
+
onComponent(customId: string, handler: RouterHandler<APIMessageComponentInteraction>): this;
|
|
10
|
+
onModal(customId: string, handler: RouterHandler<APIModalSubmitInteraction>): this;
|
|
11
|
+
dispatch(interaction: APIInteraction, ctx: InteractionContext): Promise<APIInteractionResponse | void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { InteractionType } from 'discord-api-types/v10';
|
|
2
|
+
export class InteractionRouter {
|
|
3
|
+
commandHandlers = new Map();
|
|
4
|
+
componentHandlers = new Map();
|
|
5
|
+
modalHandlers = new Map();
|
|
6
|
+
onCommand(name, handler) {
|
|
7
|
+
this.commandHandlers.set(name, handler);
|
|
8
|
+
return this;
|
|
9
|
+
}
|
|
10
|
+
onComponent(customId, handler) {
|
|
11
|
+
this.componentHandlers.set(customId, handler);
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
onModal(customId, handler) {
|
|
15
|
+
this.modalHandlers.set(customId, handler);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
async dispatch(interaction, ctx) {
|
|
19
|
+
if (interaction.type === InteractionType.ApplicationCommand) {
|
|
20
|
+
const i = interaction;
|
|
21
|
+
return this.commandHandlers.get(i.data.name)?.(i, ctx);
|
|
22
|
+
}
|
|
23
|
+
if (interaction.type === InteractionType.MessageComponent) {
|
|
24
|
+
const i = interaction;
|
|
25
|
+
return this.componentHandlers.get(i.data.custom_id)?.(i, ctx);
|
|
26
|
+
}
|
|
27
|
+
if (interaction.type === InteractionType.ModalSubmit) {
|
|
28
|
+
const i = interaction;
|
|
29
|
+
return this.modalHandlers.get(i.data.custom_id)?.(i, ctx);
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -3,7 +3,3 @@ export declare enum InteractionFlags {
|
|
|
3
3
|
IsComponentsV2 = 32768,
|
|
4
4
|
SuppressEmbeds = 4
|
|
5
5
|
}
|
|
6
|
-
/** @deprecated Use InteractionFlags instead. */
|
|
7
|
-
export { InteractionFlags as InteractionReplyFlags };
|
|
8
|
-
/** @deprecated Use InteractionFlags instead. */
|
|
9
|
-
export { InteractionFlags as InteractionFollowUpFlags };
|
|
@@ -4,7 +4,3 @@ export var InteractionFlags;
|
|
|
4
4
|
InteractionFlags[InteractionFlags["IsComponentsV2"] = 32768] = "IsComponentsV2";
|
|
5
5
|
InteractionFlags[InteractionFlags["SuppressEmbeds"] = 4] = "SuppressEmbeds";
|
|
6
6
|
})(InteractionFlags || (InteractionFlags = {}));
|
|
7
|
-
/** @deprecated Use InteractionFlags instead. */
|
|
8
|
-
export { InteractionFlags as InteractionReplyFlags };
|
|
9
|
-
/** @deprecated Use InteractionFlags instead. */
|
|
10
|
-
export { InteractionFlags as InteractionFollowUpFlags };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { APIInteraction, APIInteractionResponse, APIModalInteractionResponseCallbackData, APIMessageComponent, InteractionResponseType } from 'discord-api-types/v10';
|
|
2
|
+
export type DiscordApiVersion = '10';
|
|
3
|
+
export type JsonRecord = Record<string, unknown>;
|
|
4
|
+
export type InteractionResponseLike = APIInteractionResponse | {
|
|
5
|
+
type: InteractionResponseType;
|
|
6
|
+
data?: JsonRecord;
|
|
7
|
+
};
|
|
8
|
+
export type ModalPayload = APIModalInteractionResponseCallbackData;
|
|
9
|
+
export type ComponentPayload = APIMessageComponent;
|
|
10
|
+
export type ParsedInteraction = APIInteraction;
|
|
11
|
+
export type Snowflake = string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord API support for radio components may lag behind discord-api-types releases.
|
|
3
|
+
* These local contracts are runtime-validated and serialized as raw component payloads.
|
|
4
|
+
*/
|
|
5
|
+
export declare const RADIO_COMPONENT_TYPE: 2001;
|
|
6
|
+
export type APIRadioOption = {
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
emoji?: {
|
|
11
|
+
id?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
animated?: boolean;
|
|
14
|
+
};
|
|
15
|
+
default?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type APIRadioComponent = {
|
|
18
|
+
type: typeof RADIO_COMPONENT_TYPE;
|
|
19
|
+
custom_id: string;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
options: APIRadioOption[];
|
|
23
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class ValidationError extends Error {
|
|
2
|
+
readonly builder: string;
|
|
3
|
+
readonly field: string;
|
|
4
|
+
constructor(builder: string, field: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function assertStringLength(builder: string, field: string, value: string, min: number, max: number): void;
|
|
7
|
+
export declare function assertRange(builder: string, field: string, value: number, min: number, max: number): void;
|
|
8
|
+
export declare function assertDefined<T>(builder: string, field: string, value: T | null | undefined): T;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class ValidationError extends Error {
|
|
2
|
+
builder;
|
|
3
|
+
field;
|
|
4
|
+
constructor(builder, field, message) {
|
|
5
|
+
super(`[${builder}] ${field}: ${message}`);
|
|
6
|
+
this.builder = builder;
|
|
7
|
+
this.field = field;
|
|
8
|
+
this.name = 'ValidationError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function assertStringLength(builder, field, value, min, max) {
|
|
12
|
+
if (value.length < min || value.length > max) {
|
|
13
|
+
throw new ValidationError(builder, field, `expected length between ${min} and ${max}, got ${value.length}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function assertRange(builder, field, value, min, max) {
|
|
17
|
+
if (!Number.isInteger(value) || value < min || value > max) {
|
|
18
|
+
throw new ValidationError(builder, field, `expected integer between ${min} and ${max}, got ${value}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function assertDefined(builder, field, value) {
|
|
22
|
+
if (value === undefined || value === null) {
|
|
23
|
+
throw new ValidationError(builder, field, 'is required');
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
@@ -183,9 +183,12 @@ export function createModalSubmitInteraction(interaction, helpers) {
|
|
|
183
183
|
const getChannel = (customId) => getChannels(customId)[0];
|
|
184
184
|
const getAttachment = (customId) => {
|
|
185
185
|
const value = getComponentValue(customId);
|
|
186
|
-
if (!value
|
|
186
|
+
if (!value)
|
|
187
187
|
return undefined;
|
|
188
|
-
|
|
188
|
+
const attachmentId = Array.isArray(value) ? value[0] : value;
|
|
189
|
+
if (!attachmentId)
|
|
190
|
+
return undefined;
|
|
191
|
+
return interaction.data.resolved?.attachments?.[attachmentId];
|
|
189
192
|
};
|
|
190
193
|
return Object.assign(interaction, {
|
|
191
194
|
reply,
|
package/package.json
CHANGED
|
@@ -1,55 +1,57 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
2
|
+
"name": "@minesa-org/mini-interaction",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "Mini interaction, connecting your app with Discord via HTTP-interaction (Vercel support).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc --project tsconfig.json",
|
|
15
|
+
"postbuild": "tsx scripts/postbuild.ts",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"prepare": "npm run build",
|
|
18
|
+
"patch": "npm version patch",
|
|
19
|
+
"publish:npm": "npm publish",
|
|
20
|
+
"publish:gh": "npm publish --registry=https://npm.pkg.github.com",
|
|
21
|
+
"test": "tsx --test src/**/*.test.ts",
|
|
22
|
+
"lint:type": "tsc --noEmit"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/minesa-org/mini-interaction.git"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"discord",
|
|
33
|
+
"interactions",
|
|
34
|
+
"http-interaction",
|
|
35
|
+
"vercel",
|
|
36
|
+
"typescript"
|
|
37
|
+
],
|
|
38
|
+
"author": "Minesa",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/minesa-org/mini-interaction/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/minesa-org/mini-interaction#readme",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@vercel/functions": "^1.6.0",
|
|
46
|
+
"discord-api-types": "^0.38.32",
|
|
47
|
+
"discord-interactions": "^4.4.0",
|
|
48
|
+
"dotenv": "^17.2.3",
|
|
49
|
+
"mongodb": "^7.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^24.10.0",
|
|
53
|
+
"ts-node": "^10.9.2",
|
|
54
|
+
"tsx": "^4.20.6",
|
|
55
|
+
"typescript": "^5.9.3"
|
|
56
|
+
}
|
|
55
57
|
}
|