npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arcscord/components

v1.0.2

Published

Standalone typed helpers for Discord Components V2 messages.

Readme

@arcscord/components

npm version Discord

Standalone, typed helpers for building Discord Components V2 messages. The package depends only on Discord.js and discord-api-types; it does not require the Arcscord framework.

Using the helpers through Arcscord

Arcscord re-exports the complete Components V2 API. An Arcscord bot can import the helpers from the framework without installing this package separately:

import { actionRow, container, text, v2Message } from "arcscord";

await ctx.reply(v2Message(
  container(
    text("## Ready"),
    actionRow(confirmButton.build()),
  ),
));

Standalone installation

pnpm add @arcscord/components discord.js

Standalone usage with Discord.js

import {
  accessory,
  actionRow,
  container,
  section,
  separator,
  thumbnail,
  v2Message,
} from "@arcscord/components";
import { ButtonBuilder, ButtonStyle } from "discord.js";

const payload = v2Message(
  container(
    { accentColor: 0x5865F2 },
    "## Support",
    section(
      "Open a support request.",
      accessory(thumbnail({ media: { url: "https://example.com/support.png" } })),
    ),
    separator({ divider: true, spacing: "large" }),
    actionRow(
      new ButtonBuilder()
        .setCustomId("support")
        .setLabel("Open")
        .setStyle(ButtonStyle.Primary),
    ),
  ),
);

This example does not require an Arcscord client, context, manager, or error package. Pass the result to any compatible Discord.js reply or edit method. v2Message adds MessageFlags.IsComponentsV2 automatically.

When converting an existing legacy message, pass the reset values required by Discord before the first component. The returned MessageV2MigrationReplyOptions preserves them in the edit payload:

await message.edit(v2Message(
  { content: null, embeds: [], stickers: [] },
  "Replacement Components V2 content",
));

Accepted inputs

Nested components accept:

  • Discord.js *ComponentData objects;
  • official Discord.js builders;
  • raw API*Component objects from discord-api-types;
  • strings wherever a text display is allowed.

Builders and raw API objects are recursively normalized to Discord.js camelCase component data. actionRow accepts either one to five buttons or exactly one string, user, role, mentionable, or channel select menu. Existing action rows can also be passed directly to container or v2Message.

container() only constructs a new container from options and children. Pass a complete ContainerBuilder, Discord.js container datum, or raw APIContainerComponent directly to v2Message(), or normalize it explicitly with validateContainer().

Runtime validation

Every helper runs a single serialization, normalization, and validation pipeline before returning. Invalid component fields, nesting, protocol restrictions, cardinalities, duplicate component/custom IDs or select values, unsupported message flags, messages containing more than 40 total components, and messages exceeding 4,000 cumulative Text Display characters fail locally instead of being sent to Discord. Containers accept up to 40 direct children, subject to the same recursive 40-component message limit.

Component type errors stay neutral: unexpected-component-type reports a discriminator outside the accepted set, while component-placement reports a known Discord component used at an invalid nesting location. Neither error assumes whether the input is a typo or an API addition.

The same pipeline is available through named exports such as validateButton, validateSection, validateContainer, and validateV2Message. Successful calls return newly constructed, recursively normalized Discord.js camelCase data. A failed call throws MessageComponentValidationError, whose rule, path, componentType, and details fields can be used for structured reporting:

import {
  isMessageComponentValidationError,
  validateV2Message,
} from "@arcscord/components";

try {
  validateV2Message(payload);
}
catch (error) {
  if (isMessageComponentValidationError(error)) {
    console.error(error.rule, error.path);
  }
}

arcscord directly re-exports these functions, so direct calls preserve the same MessageComponentValidationError, function identity, overloads, and editor documentation. When the error crosses an Arcscord command, component, event, or middleware execution boundary, the framework converts the defect into an ArcscordError with code MESSAGE_COMPONENT_VALIDATION_FAILED. Use normalizeArcscordError(error) when the same conversion is needed manually. The standalone package has no dependency on Arcscord's error packages.

Nesting

| Parent | Allowed children | | --- | --- | | v2Message | text, action row, container, file, media gallery, section, separator | | container | text, action row, file, media gallery, section, separator | | section | one or more text displays followed by one accessory(...) | | accessory | one button or thumbnail | | actionRow | one to five buttons, or exactly one select menu |

The helpers, validators, return values, and direct validation errors are identical through @arcscord/components and arcscord. Arcscord only adapts a validation error when it enters the framework execution pipeline or when normalizeArcscordError is called explicitly.