diff --git a/docs/classes/DiscordJsAdapter.html b/docs/classes/DiscordJsAdapter.html index 417afdc..eb7b7a1 100644 --- a/docs/classes/DiscordJsAdapter.html +++ b/docs/classes/DiscordJsAdapter.html @@ -1 +1 @@ -DiscordJsAdapter | reacord
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class DiscordJsAdapter

Hierarchy

  • DiscordJsAdapter

Implements

  • Adapter<Discord.CommandInteraction>

Index

Constructors

Constructors

constructor

Generated using TypeDoc

\ No newline at end of file +DiscordJsAdapter | reacord
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class DiscordJsAdapter

Hierarchy

  • DiscordJsAdapter

Implements

  • Adapter<Discord.CommandInteraction>

Index

Constructors

Constructors

constructor

  • Parameters

    • client: Client<boolean>

    Returns DiscordJsAdapter

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/Reacord.html b/docs/classes/Reacord.html index cf93085..1f76338 100644 --- a/docs/classes/Reacord.html +++ b/docs/classes/Reacord.html @@ -1 +1 @@ -Reacord | reacord
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class Reacord<InteractionInit>

Type parameters

  • InteractionInit

Hierarchy

  • Reacord

Index

Constructors

constructor

Methods

createCommandReply

Generated using TypeDoc

\ No newline at end of file +Reacord | reacord
Options
All
  • Public
  • Public/Protected
  • All
Menu

Class Reacord<InteractionInit>

Type parameters

  • InteractionInit

Hierarchy

  • Reacord

Index

Constructors

constructor

  • Type parameters

    • InteractionInit

    Parameters

    Returns Reacord<InteractionInit>

Methods

createCommandReply

  • Parameters

    • target: InteractionInit

    Returns ReacordInstance

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html index ecf2eab..320071f 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -1,4 +1,4 @@ -reacord
Options
All
  • Public
  • Public/Protected
  • All
Menu

reacord

Index

Type aliases

Adapter

Adapter<InteractionInit>: { }

Type parameters

  • InteractionInit

Type declaration

    ButtonClickEvent

    ButtonClickEvent: {}

    Type declaration

      ButtonProps

      ButtonProps: { disabled?: boolean; emoji?: string; label?: string; style?: "primary" | "secondary" | "success" | "danger"; onClick: any }

      Type declaration

      • Optional disabled?: boolean
      • Optional emoji?: string
      • Optional label?: string
      • Optional style?: "primary" | "secondary" | "success" | "danger"
      • onClick:function

      EmbedAuthorProps

      EmbedAuthorProps: { children?: string; iconUrl?: string; name?: string; url?: string }

      Type declaration

      • Optional children?: string
      • Optional iconUrl?: string
      • Optional name?: string
      • Optional url?: string

      EmbedFieldProps

      EmbedFieldProps: { children?: string; inline?: boolean; name: string; value?: string }

      Type declaration

      • Optional children?: string
      • Optional inline?: boolean
      • name: string
      • Optional value?: string

      EmbedFooterProps

      EmbedFooterProps: { children?: string; iconUrl?: string; text?: string; timestamp?: string | number | Date }

      Type declaration

      • Optional children?: string
      • Optional iconUrl?: string
      • Optional text?: string
      • Optional timestamp?: string | number | Date

      EmbedImageProps

      EmbedImageProps: { url: string }

      Type declaration

      • url: string

      EmbedProps

      EmbedProps: { author?: { iconUrl?: string; name: string; url?: string }; children?: React.ReactNode; color?: number; description?: string; fields?: { inline?: boolean; name: string; value: string }[]; footer?: { iconUrl?: string; text: string }; image?: { url: string }; thumbnail?: { url: string }; timestamp?: string | number | Date; title?: string; url?: string; video?: { url: string } }

      Type declaration

      • Optional author?: { iconUrl?: string; name: string; url?: string }
        • Optional iconUrl?: string
        • name: string
        • Optional url?: string
      • Optional children?: React.ReactNode
      • Optional color?: number
      • Optional description?: string
      • Optional fields?: { inline?: boolean; name: string; value: string }[]
      • Optional footer?: { iconUrl?: string; text: string }
        • Optional iconUrl?: string
        • text: string
      • Optional image?: { url: string }
        • url: string
      • Optional thumbnail?: { url: string }
        • url: string
      • Optional timestamp?: string | number | Date
      • Optional title?: string
      • Optional url?: string
      • Optional video?: { url: string }
        • url: string

      EmbedThumbnailProps

      EmbedThumbnailProps: { url: string }

      Type declaration

      • url: string

      EmbedTitleProps

      EmbedTitleProps: { children: string; url?: string }

      Type declaration

      • children: string
      • Optional url?: string

      LinkProps

      LinkProps: { children?: string; disabled?: boolean; emoji?: string; label?: string; url: string }

      Type declaration

      • Optional children?: string
      • Optional disabled?: boolean
      • Optional emoji?: string
      • Optional label?: string
      • url: string

      ReacordConfig

      ReacordConfig<InteractionInit>: { adapter: Adapter<InteractionInit>; maxInstances?: number }

      Type parameters

      • InteractionInit

      Type declaration

      • adapter: Adapter<InteractionInit>
      • Optional maxInstances?: number
        +reacord
        Options
        All
        • Public
        • Public/Protected
        • All
        Menu

        reacord

        Index

        Type aliases

        Adapter

        Adapter<InteractionInit>: { }

        Type parameters

        • InteractionInit

        Type declaration

          ButtonClickEvent

          ButtonClickEvent: {}

          Type declaration

            ButtonProps

            ButtonProps: { disabled?: boolean; emoji?: string; label?: string; style?: "primary" | "secondary" | "success" | "danger"; onClick: any }

            Type declaration

            • Optional disabled?: boolean
            • Optional emoji?: string
            • Optional label?: string
            • Optional style?: "primary" | "secondary" | "success" | "danger"
            • onClick:function
              • Parameters

                Returns void

            EmbedAuthorProps

            EmbedAuthorProps: { children?: string; iconUrl?: string; name?: string; url?: string }

            Type declaration

            • Optional children?: string
            • Optional iconUrl?: string
            • Optional name?: string
            • Optional url?: string

            EmbedFieldProps

            EmbedFieldProps: { children?: string; inline?: boolean; name: string; value?: string }

            Type declaration

            • Optional children?: string
            • Optional inline?: boolean
            • name: string
            • Optional value?: string

            EmbedFooterProps

            EmbedFooterProps: { children?: string; iconUrl?: string; text?: string; timestamp?: string | number | Date }

            Type declaration

            • Optional children?: string
            • Optional iconUrl?: string
            • Optional text?: string
            • Optional timestamp?: string | number | Date

            EmbedImageProps

            EmbedImageProps: { url: string }

            Type declaration

            • url: string

            EmbedProps

            EmbedProps: { author?: { iconUrl?: string; name: string; url?: string }; children?: React.ReactNode; color?: number; description?: string; fields?: { inline?: boolean; name: string; value: string }[]; footer?: { iconUrl?: string; text: string }; image?: { url: string }; thumbnail?: { url: string }; timestamp?: string | number | Date; title?: string; url?: string; video?: { url: string } }

            Type declaration

            • Optional author?: { iconUrl?: string; name: string; url?: string }
              • Optional iconUrl?: string
              • name: string
              • Optional url?: string
            • Optional children?: React.ReactNode
            • Optional color?: number
            • Optional description?: string
            • Optional fields?: { inline?: boolean; name: string; value: string }[]
            • Optional footer?: { iconUrl?: string; text: string }
              • Optional iconUrl?: string
              • text: string
            • Optional image?: { url: string }
              • url: string
            • Optional thumbnail?: { url: string }
              • url: string
            • Optional timestamp?: string | number | Date
            • Optional title?: string
            • Optional url?: string
            • Optional video?: { url: string }
              • url: string

            EmbedThumbnailProps

            EmbedThumbnailProps: { url: string }

            Type declaration

            • url: string

            EmbedTitleProps

            EmbedTitleProps: { children: string; url?: string }

            Type declaration

            • children: string
            • Optional url?: string

            LinkProps

            LinkProps: { children?: string; disabled?: boolean; emoji?: string; label?: string; url: string }

            Type declaration

            • Optional children?: string
            • Optional disabled?: boolean
            • Optional emoji?: string
            • Optional label?: string
            • url: string

            ReacordConfig

            ReacordConfig<InteractionInit>: { adapter: Adapter<InteractionInit>; maxInstances?: number }

            Type parameters

            • InteractionInit

            Type declaration

            • adapter: Adapter<InteractionInit>
            • Optional maxInstances?: number

              The max number of active instances. When this limit is exceeded, the oldest instances will be disabled.

              -

            ReacordInstance

            ReacordInstance: { deactivate: any; render: any }

            Type declaration

            • deactivate:function
              • deactivate(): void
            • render:function
              • render(content: ReactNode): void

            Functions

            Button

            Embed

            EmbedAuthor

            EmbedField

            EmbedFooter

            EmbedImage

            EmbedThumbnail

            EmbedTitle

            Link

            Legend

            • Constructor
            • Method

            Settings

            Theme

            Generated using TypeDoc

            \ No newline at end of file +

          ReacordInstance

          ReacordInstance: { deactivate: any; render: any }

          Type declaration

          • deactivate:function
            • deactivate(): void
            • Returns void

          • render:function
            • render(content: ReactNode): void
            • Parameters

              • content: ReactNode

              Returns void

          Functions

          Button

          • Parameters

            Returns Element

          Embed

          • Parameters

            Returns Element

          EmbedAuthor

          • Parameters

            Returns Element

          EmbedField

          • Parameters

            Returns Element

          EmbedFooter

          • Parameters

            Returns Element

          EmbedImage

          • Parameters

            Returns Element

          EmbedThumbnail

          • Parameters

            Returns Element

          EmbedTitle

          • Parameters

            Returns Element

          Link

          • Parameters

            Returns Element

          Generated using TypeDoc

          \ No newline at end of file diff --git a/library/adapter/adapter.ts b/library/adapter/adapter.ts deleted file mode 100644 index 1007e9a..0000000 --- a/library/adapter/adapter.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { CommandInteraction, ComponentInteraction } from "../interaction" - -export type Adapter = { - /** - * @internal - */ - addComponentInteractionListener( - listener: (interaction: ComponentInteraction) => void, - ): void - - /** - * @internal - */ - createCommandInteraction(interactionInfo: InteractionInit): CommandInteraction -} diff --git a/library/adapter/test-adapter.ts b/library/adapter/test-adapter.ts deleted file mode 100644 index cfd2a7e..0000000 --- a/library/adapter/test-adapter.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { nanoid } from "nanoid" -import { raise } from "../../helpers/raise" -import type { - ButtonInteraction, - CommandInteraction, - ComponentInteraction, -} from "../interaction" -import type { Message, MessageButtonOptions, MessageOptions } from "../message" -import type { Adapter } from "./adapter" - -export class TestAdapter implements Adapter<{}> { - readonly messages: TestMessage[] = [] - - // eslint-disable-next-line class-methods-use-this - private componentInteractionListener: ( - interaction: ComponentInteraction, - ) => void = () => {} - - addComponentInteractionListener( - listener: (interaction: ComponentInteraction) => void, - ): void { - this.componentInteractionListener = listener - } - - // eslint-disable-next-line class-methods-use-this - createCommandInteraction( - interaction: CommandInteraction, - ): CommandInteraction { - return interaction - } - - findButtonByLabel(label: string) { - for (const message of this.messages) { - for (const component of message.options.actionRows.flat()) { - if (component.type === "button" && component.label === label) { - return this.createButtonActions(component, message) - } - } - } - raise(`Couldn't find button with label "${label}"`) - } - - private createButtonActions( - button: MessageButtonOptions, - message: TestMessage, - ) { - return { - click: () => { - this.componentInteractionListener( - new TestButtonInteraction(button.customId, message), - ) - }, - } - } -} - -export class TestMessage implements Message { - constructor(public options: MessageOptions) {} - - async edit(options: MessageOptions): Promise { - this.options = options - } - - async disableComponents(): Promise { - for (const row of this.options.actionRows) { - for (const action of row) { - if (action.type === "button") { - action.disabled = true - } - } - } - } -} - -export class TestCommandInteraction implements CommandInteraction { - readonly type = "command" - readonly id = "test-command-interaction" - readonly channelId = "test-channel-id" - - constructor(private adapter: TestAdapter) {} - - private createMesssage(messageOptions: MessageOptions): Message { - const message = new TestMessage(messageOptions) - this.adapter.messages.push(message) - return message - } - - reply(messageOptions: MessageOptions): Promise { - return Promise.resolve(this.createMesssage(messageOptions)) - } - - followUp(messageOptions: MessageOptions): Promise { - return Promise.resolve(this.createMesssage(messageOptions)) - } -} - -export class TestButtonInteraction implements ButtonInteraction { - readonly type = "button" - readonly id = nanoid() - readonly channelId = "test-channel-id" - - constructor(readonly customId: string, readonly message: TestMessage) {} - - async update(options: MessageOptions): Promise { - this.message.options = options - } -} diff --git a/library/core/adapters/adapter.ts b/library/core/adapters/adapter.ts new file mode 100644 index 0000000..3eb3434 --- /dev/null +++ b/library/core/adapters/adapter.ts @@ -0,0 +1,18 @@ +import type { + CommandInteraction, + ComponentInteraction, +} from "../../internal/interaction" + +export type Adapter = { + /** + * @internal + */ + addComponentInteractionListener( + listener: (interaction: ComponentInteraction) => void, + ): void + + /** + * @internal + */ + createCommandInteraction(init: CommandReplyInit): CommandInteraction +} diff --git a/library/adapter/discord-js-adapter.ts b/library/core/adapters/discord-js-adapter.ts similarity index 91% rename from library/adapter/discord-js-adapter.ts rename to library/core/adapters/discord-js-adapter.ts index 7f418f9..6af88e8 100644 --- a/library/adapter/discord-js-adapter.ts +++ b/library/core/adapters/discord-js-adapter.ts @@ -1,8 +1,11 @@ import type * as Discord from "discord.js" -import { raise } from "../../helpers/raise" -import { toUpper } from "../../helpers/to-upper" -import type { CommandInteraction, ComponentInteraction } from "../interaction" -import type { Message, MessageOptions } from "../message" +import { raise } from "../../../helpers/raise" +import { toUpper } from "../../../helpers/to-upper" +import type { + CommandInteraction, + ComponentInteraction, +} from "../../internal/interaction" +import type { Message, MessageOptions } from "../../internal/message" import type { Adapter } from "./adapter" export class DiscordJsAdapter implements Adapter { diff --git a/library/button.tsx b/library/core/components/button.tsx similarity index 82% rename from library/button.tsx rename to library/core/components/button.tsx index c58e2f1..dadf7b4 100644 --- a/library/button.tsx +++ b/library/core/components/button.tsx @@ -1,10 +1,10 @@ import { nanoid } from "nanoid" import React from "react" -import { last } from "../helpers/last.js" -import { ReacordElement } from "./element.js" -import type { ComponentInteraction } from "./interaction" -import type { MessageOptions } from "./message" -import { Node } from "./node.js" +import { last } from "../../../helpers/last.js" +import { ReacordElement } from "../../internal/element.js" +import type { ComponentInteraction } from "../../internal/interaction" +import type { MessageOptions } from "../../internal/message" +import { Node } from "../../internal/node.js" export type ButtonProps = { label?: string diff --git a/library/embed/embed-author.tsx b/library/core/components/embed-author.tsx similarity index 92% rename from library/embed/embed-author.tsx rename to library/core/components/embed-author.tsx index b6b547d..86828e4 100644 --- a/library/embed/embed-author.tsx +++ b/library/core/components/embed-author.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ReacordElement } from "../element.js" +import { ReacordElement } from "../../internal/element.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/embed/embed-child.ts b/library/core/components/embed-child.ts similarity index 79% rename from library/embed/embed-child.ts rename to library/core/components/embed-child.ts index 0fa58f7..851f059 100644 --- a/library/embed/embed-child.ts +++ b/library/core/components/embed-child.ts @@ -1,4 +1,4 @@ -import { Node } from "../node.js" +import { Node } from "../../internal/node.js" import type { EmbedOptions } from "./embed-options" export abstract class EmbedChildNode extends Node { diff --git a/library/embed/embed-field.tsx b/library/core/components/embed-field.tsx similarity index 92% rename from library/embed/embed-field.tsx rename to library/core/components/embed-field.tsx index f5d07ac..a46a01b 100644 --- a/library/embed/embed-field.tsx +++ b/library/core/components/embed-field.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ReacordElement } from "../element.js" +import { ReacordElement } from "../../internal/element.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/embed/embed-footer.tsx b/library/core/components/embed-footer.tsx similarity index 93% rename from library/embed/embed-footer.tsx rename to library/core/components/embed-footer.tsx index fe92ce0..950b854 100644 --- a/library/embed/embed-footer.tsx +++ b/library/core/components/embed-footer.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ReacordElement } from "../element.js" +import { ReacordElement } from "../../internal/element.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/embed/embed-image.tsx b/library/core/components/embed-image.tsx similarity index 89% rename from library/embed/embed-image.tsx rename to library/core/components/embed-image.tsx index 513d4ec..c3c86ef 100644 --- a/library/embed/embed-image.tsx +++ b/library/core/components/embed-image.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ReacordElement } from "../element.js" +import { ReacordElement } from "../../internal/element.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/embed/embed-options.ts b/library/core/components/embed-options.ts similarity index 100% rename from library/embed/embed-options.ts rename to library/core/components/embed-options.ts diff --git a/library/embed/embed-thumbnail.tsx b/library/core/components/embed-thumbnail.tsx similarity index 90% rename from library/embed/embed-thumbnail.tsx rename to library/core/components/embed-thumbnail.tsx index e4b28a0..ea4a084 100644 --- a/library/embed/embed-thumbnail.tsx +++ b/library/core/components/embed-thumbnail.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ReacordElement } from "../element.js" +import { ReacordElement } from "../../internal/element.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/embed/embed-title.tsx b/library/core/components/embed-title.tsx similarity index 90% rename from library/embed/embed-title.tsx rename to library/core/components/embed-title.tsx index 4470ab6..d788ba3 100644 --- a/library/embed/embed-title.tsx +++ b/library/core/components/embed-title.tsx @@ -1,5 +1,5 @@ import React from "react" -import { ReacordElement } from "../element.js" +import { ReacordElement } from "../../internal/element.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/embed/embed.tsx b/library/core/components/embed.tsx similarity index 81% rename from library/embed/embed.tsx rename to library/core/components/embed.tsx index 7c05678..f957f53 100644 --- a/library/embed/embed.tsx +++ b/library/core/components/embed.tsx @@ -1,9 +1,9 @@ import React from "react" -import { snakeCaseDeep } from "../../helpers/convert-object-property-case" -import { omit } from "../../helpers/omit" -import { ReacordElement } from "../element.js" -import type { MessageOptions } from "../message" -import { Node } from "../node.js" +import { snakeCaseDeep } from "../../../helpers/convert-object-property-case" +import { omit } from "../../../helpers/omit" +import { ReacordElement } from "../../internal/element.js" +import type { MessageOptions } from "../../internal/message" +import { Node } from "../../internal/node.js" import { EmbedChildNode } from "./embed-child.js" import type { EmbedOptions } from "./embed-options" diff --git a/library/link.tsx b/library/core/components/link.tsx similarity index 79% rename from library/link.tsx rename to library/core/components/link.tsx index fd26051..fdbd75e 100644 --- a/library/link.tsx +++ b/library/core/components/link.tsx @@ -1,8 +1,8 @@ import React from "react" -import { last } from "../helpers/last.js" -import { ReacordElement } from "./element.js" -import type { MessageOptions } from "./message" -import { Node } from "./node.js" +import { last } from "../../../helpers/last.js" +import { ReacordElement } from "../../internal/element.js" +import type { MessageOptions } from "../../internal/message" +import { Node } from "../../internal/node.js" export type LinkProps = { label?: string diff --git a/library/reacord.ts b/library/core/reacord.ts similarity index 90% rename from library/reacord.ts rename to library/core/reacord.ts index 3abf618..cacb349 100644 --- a/library/reacord.ts +++ b/library/core/reacord.ts @@ -1,7 +1,7 @@ import type { ReactNode } from "react" -import type { Adapter } from "./adapter/adapter" -import { reconciler } from "./reconciler.js" -import { Renderer } from "./renderer.js" +import { reconciler } from "../internal/reconciler.js" +import { Renderer } from "../internal/renderer.js" +import type { Adapter } from "./adapters/adapter" export type ReacordConfig = { adapter: Adapter diff --git a/library/container.ts b/library/internal/container.ts similarity index 100% rename from library/container.ts rename to library/internal/container.ts diff --git a/library/element.ts b/library/internal/element.ts similarity index 86% rename from library/element.ts rename to library/internal/element.ts index 497de3c..ab5f9ac 100644 --- a/library/element.ts +++ b/library/internal/element.ts @@ -1,6 +1,6 @@ import type { ReactNode } from "react" import React from "react" -import type { Node } from "./node.js" +import type { Node } from "./node" export function ReacordElement(props: { props: Props diff --git a/library/interaction.ts b/library/internal/interaction.ts similarity index 100% rename from library/interaction.ts rename to library/internal/interaction.ts diff --git a/library/message.ts b/library/internal/message.ts similarity index 90% rename from library/message.ts rename to library/internal/message.ts index d8c56ef..f1794b3 100644 --- a/library/message.ts +++ b/library/internal/message.ts @@ -1,4 +1,4 @@ -import type { EmbedOptions } from "./embed/embed-options" +import type { EmbedOptions } from "../core/components/embed-options" export type MessageOptions = { content: string diff --git a/library/node.ts b/library/internal/node.ts similarity index 100% rename from library/node.ts rename to library/internal/node.ts diff --git a/library/reconciler.ts b/library/internal/reconciler.ts similarity index 96% rename from library/reconciler.ts rename to library/internal/reconciler.ts index 933c3d0..dd0c6a9 100644 --- a/library/reconciler.ts +++ b/library/internal/reconciler.ts @@ -1,9 +1,9 @@ import type { HostConfig } from "react-reconciler" import ReactReconciler from "react-reconciler" -import { raise } from "../helpers/raise.js" +import { raise } from "../../helpers/raise.js" import { Node } from "./node.js" import type { Renderer } from "./renderer.js" -import { TextNode } from "./text.js" +import { TextNode } from "./text-node.js" const config: HostConfig< string, // Type, diff --git a/library/renderer.ts b/library/internal/renderer.ts similarity index 100% rename from library/renderer.ts rename to library/internal/renderer.ts diff --git a/library/text.ts b/library/internal/text-node.ts similarity index 100% rename from library/text.ts rename to library/internal/text-node.ts diff --git a/library/main.ts b/library/main.ts index 899eb32..7d4a1ee 100644 --- a/library/main.ts +++ b/library/main.ts @@ -1,12 +1,12 @@ -export * from "./adapter/adapter" -export * from "./adapter/discord-js-adapter" -export * from "./button" -export * from "./embed/embed" -export * from "./embed/embed-author" -export * from "./embed/embed-field" -export * from "./embed/embed-footer" -export * from "./embed/embed-image" -export * from "./embed/embed-thumbnail" -export * from "./embed/embed-title" -export * from "./link" -export * from "./reacord" +export * from "./core/adapters/adapter" +export * from "./core/adapters/discord-js-adapter" +export * from "./core/components/button" +export * from "./core/components/embed" +export * from "./core/components/embed-author" +export * from "./core/components/embed-field" +export * from "./core/components/embed-footer" +export * from "./core/components/embed-image" +export * from "./core/components/embed-thumbnail" +export * from "./core/components/embed-title" +export * from "./core/components/link" +export * from "./core/reacord" diff --git a/library/testing.ts b/library/testing.ts index b255080..b33da92 100644 --- a/library/testing.ts +++ b/library/testing.ts @@ -1 +1,111 @@ -export * from "./adapter/test-adapter" +/* eslint-disable class-methods-use-this */ +/* eslint-disable require-await */ +import { nanoid } from "nanoid" +import { raise } from "../helpers/raise" +import type { Adapter } from "./core/adapters/adapter" +import type { + ButtonInteraction, + CommandInteraction, + ComponentInteraction, +} from "./internal/interaction" +import type { + Message, + MessageButtonOptions, + MessageOptions, +} from "./internal/message" + +export class TestAdapter implements Adapter { + readonly messages: TestMessage[] = [] + + private componentInteractionListener: ( + interaction: ComponentInteraction, + ) => void = () => {} + + addComponentInteractionListener( + listener: (interaction: ComponentInteraction) => void, + ): void { + this.componentInteractionListener = listener + } + + createCommandInteraction( + interaction: CommandInteraction, + ): CommandInteraction { + return interaction + } + + findButtonByLabel(label: string) { + for (const message of this.messages) { + for (const component of message.options.actionRows.flat()) { + if (component.type === "button" && component.label === label) { + return this.createButtonActions(component, message) + } + } + } + raise(`Couldn't find button with label "${label}"`) + } + + private createButtonActions( + button: MessageButtonOptions, + message: TestMessage, + ) { + return { + click: () => { + this.componentInteractionListener( + new TestButtonInteraction(button.customId, message), + ) + }, + } + } +} + +export class TestMessage implements Message { + constructor(public options: MessageOptions) {} + + async edit(options: MessageOptions): Promise { + this.options = options + } + + async disableComponents(): Promise { + for (const row of this.options.actionRows) { + for (const action of row) { + if (action.type === "button") { + action.disabled = true + } + } + } + } +} + +export class TestCommandInteraction implements CommandInteraction { + readonly type = "command" + readonly id = "test-command-interaction" + readonly channelId = "test-channel-id" + + constructor(private adapter: TestAdapter) {} + + private createMesssage(messageOptions: MessageOptions): Message { + const message = new TestMessage(messageOptions) + this.adapter.messages.push(message) + return message + } + + reply(messageOptions: MessageOptions): Promise { + return Promise.resolve(this.createMesssage(messageOptions)) + } + + followUp(messageOptions: MessageOptions): Promise { + return Promise.resolve(this.createMesssage(messageOptions)) + } +} + +export class TestButtonInteraction implements ButtonInteraction { + readonly type = "button" + readonly id = nanoid() + readonly channelId = "test-channel-id" + + constructor(readonly customId: string, readonly message: TestMessage) {} + + async update(options: MessageOptions): Promise { + this.message.options = options + } +}