Skip to content

feat(structures): add Guild structures and additional bitfields to @discordjs/structures#11355

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/add-guild-structures
Draft

feat(structures): add Guild structures and additional bitfields to @discordjs/structures#11355
Copilot wants to merge 4 commits intomainfrom
copilot/add-guild-structures

Conversation

Copy link
Contributor

Copilot AI commented Dec 9, 2025

Implements Sprint 1 of the greenfield rewrite: core Guild-related structures and foundational bitfields for bot functionality.

Structures Added (packages/structures/src/guilds/)

  • Guild - Server structure with 30+ properties (channels, features, limits, moderation settings)
  • GuildMember - Member structure with optimized timestamp storage (joined_at, premium_since, communication_disabled_until stored as numbers, converted to ISO strings in toJSON())
  • Role - Role structure with computed hexColor property
  • RoleTags - Special role type identifiers (bot, integration, premium subscriber)
  • GuildEmoji, GuildBan, WelcomeScreen, WelcomeChannel

Bitfields Added (packages/structures/src/bitfields/)

  • GuildMemberFlagsBitField - Member flags (DidRejoin, CompletedOnboarding, BypassesVerification)
  • RoleFlagsBitField - Role flags (InPrompt)
  • UserFlagsBitField - User flags (Staff, Partner, Hypesquad, VerifiedBot, etc.)
  • SystemChannelFlagsBitField - System channel notification toggles

Implementation Notes

  • Structures marked abstract where substructures (User, AvatarDecorationData) require instantiation by extending classes
  • GuildMember timestamp optimization follows Invite pattern: removes raw timestamps from kData, stores as numbers, reconstructs ISO format in toJSON()
  • All types imported from discord-api-types/v10

Usage Example

import { Guild, GuildMember, Role, GuildMemberFlagsBitField } from '@discordjs/structures';

// Structures work with API data
const member = new GuildMember(apiData);
console.log(member.joinedAt); // Date object
console.log(member.isCommunicationDisabled); // boolean computed property

// Bitfields for flag manipulation
const flags = new GuildMemberFlagsBitField();
flags.add(GuildMemberFlags.CompletedOnboarding);
console.log(flags.has(GuildMemberFlags.DidRejoin)); // false

Testing

  • 50 tests for Guild structures (property access, timestamp optimization, JSON serialization)
  • 31 tests for bitfields (add/remove/has operations, serialization)
Original prompt

Overview

As part of the greenfield rewrite plan for discord.js, we need to expand the @discordjs/structures package with missing entity structures. This PR focuses on Sprint 1: adding Guild-related structures and additional bitfields that are foundational for most bot functionality.

Current State

The packages/structures package already has a solid foundation with:

  • Base Structure class with kData, kPatch, kClone, data templates, and optimization support
  • Sophisticated Mixin system for composing structures
  • Channels (all types), Messages, Users, Polls, Stickers, Invites
  • Core bitfields (BitField, PermissionsBitField, MessageFlagsBitField, ChannelFlagsBitField, AttachmentFlagsBitField)

Structures to Implement

Guild-related Structures (Priority)

  1. Guild - Core guild/server structure

    • Properties: id, name, icon, splash, discoverySplash, ownerId, afkChannelId, afkTimeout, widgetEnabled, widgetChannelId, verificationLevel, defaultMessageNotifications, explicitContentFilter, features, mfaLevel, applicationId, systemChannelId, systemChannelFlags, rulesChannelId, maxPresences, maxMembers, vanityUrlCode, description, banner, premiumTier, premiumSubscriptionCount, preferredLocale, publicUpdatesChannelId, maxVideoChannelUsers, maxStageVideoChannelUsers, approximateMemberCount, approximatePresenceCount, welcomeScreen, nsfwLevel, premiumProgressBarEnabled, safetyAlertsChannelId
    • Use APIGuild from discord-api-types
  2. GuildMember - Guild member structure

    • Properties: userId, nick, avatar, roles, joinedAt, premiumSince, deaf, mute, flags, pending, permissions, communicationDisabledUntil, avatarDecorationData
    • Use APIGuildMember from discord-api-types
  3. Role - Role structure

    • Properties: id, name, color, hoist, icon, unicodeEmoji, position, permissions, managed, mentionable, tags, flags
    • Use APIRole from discord-api-types
  4. GuildEmoji - Guild emoji structure

    • Properties: id, name, roles, user, requireColons, managed, animated, available
    • Use APIEmoji from discord-api-types
  5. GuildBan - Guild ban structure

    • Properties: reason, user
    • Use APIBan from discord-api-types
  6. RoleTags - Role tags structure

    • Properties: botId, integrationId, premiumSubscriber, subscriptionListingId, availableForPurchase, guildConnections
    • Use APIRoleTags from discord-api-types
  7. WelcomeScreen - Guild welcome screen structure

    • Properties: description, welcomeChannels
    • Use APIGuildWelcomeScreen from discord-api-types
  8. WelcomeChannel - Welcome screen channel structure

    • Properties: channelId, description, emojiId, emojiName
    • Use APIGuildWelcomeScreenChannel from discord-api-types

Additional Bitfields

  1. GuildMemberFlagsBitField - Using GuildMemberFlags from discord-api-types
  2. RoleFlagsBitField - Using RoleFlags from discord-api-types
  3. UserFlagsBitField - Using UserFlags from discord-api-types
  4. SystemChannelFlagsBitField - Using GuildSystemChannelFlags from discord-api-types
  5. GuildFlagsBitField - Using GuildFeature flags (if applicable)

Implementation Guidelines

  1. Follow existing patterns - Use the same structure as existing files in packages/structures/src/
  2. Extend Structure base class - All structures should extend Structure<APIType, OmittedKeys>
  3. Use data templates - Implement DataTemplate for optimized data storage where appropriate
  4. Implement optimizeData - For timestamp fields and other optimizable data
  5. Use discord-api-types - Import types from discord-api-types/v10
  6. Add proper JSDoc - Document all public properties and methods
  7. Export from index - Add new structures to packages/structures/src/index.ts
  8. Create guilds/ folder - Organize guild structures in packages/structures/src/guilds/

File Structure

packages/structures/src/
├── guilds/
│   ├── index.ts
│   ├── Guild.ts
│   ├── GuildMember.ts
│   ├── Role.ts
│   ├── RoleTags.ts
│   ├── GuildEmoji.ts
│   ├── GuildBan.ts
│   ├── WelcomeScreen.ts
│   └── WelcomeChannel.ts
├── bitfields/
│   ├── ... (existing)
│   ├── GuildMemberFlagsBitField.ts
│   ├── RoleFlagsBitField.ts
│   ├── UserFlagsBitField.ts
│   └── SystemChannelFlagsBitField.ts
└── index.ts (updated to export guilds/)

Example Implementation Pattern

Based on existing structures like User.ts:

import type { APIGuild } from 'discord-api-types/v10';
import { Structure } from '../Structure.js';
import { kData } from '../utils/symbols.js';
import { toTimestamp, type TimestampResolvable } from '../utils/optimization.js';

type GuildOmittedKeys = '';

export class Guild extends Structure<APIGuild, GuildOmittedKey...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created as a result of the following prompt from Copilot chat.*
> ## Overview
> 
> As part of the greenfield rewrite plan for discord.js, we need to expand the `@discordjs/structures` package with missing entity structures. This PR focuses on Sprint 1: adding Guild-related structures and additional bitfields that are foundational for most bot functionality.
> 
> ## Current State
> 
> The `packages/structures` package already has a solid foundation with:
> - Base `Structure` class with `kData`, `kPatch`, `kClone`, data templates, and optimization support
> - Sophisticated `Mixin` system for composing structures
> - Channels (all types), Messages, Users, Polls, Stickers, Invites
> - Core bitfields (`BitField`, `PermissionsBitField`, `MessageFlagsBitField`, `ChannelFlagsBitField`, `AttachmentFlagsBitField`)
> 
> ## Structures to Implement
> 
> ### Guild-related Structures (Priority)
> 
> 1. **`Guild`** - Core guild/server structure
>    - Properties: `id`, `name`, `icon`, `splash`, `discoverySplash`, `ownerId`, `afkChannelId`, `afkTimeout`, `widgetEnabled`, `widgetChannelId`, `verificationLevel`, `defaultMessageNotifications`, `explicitContentFilter`, `features`, `mfaLevel`, `applicationId`, `systemChannelId`, `systemChannelFlags`, `rulesChannelId`, `maxPresences`, `maxMembers`, `vanityUrlCode`, `description`, `banner`, `premiumTier`, `premiumSubscriptionCount`, `preferredLocale`, `publicUpdatesChannelId`, `maxVideoChannelUsers`, `maxStageVideoChannelUsers`, `approximateMemberCount`, `approximatePresenceCount`, `welcomeScreen`, `nsfwLevel`, `premiumProgressBarEnabled`, `safetyAlertsChannelId`
>    - Use `APIGuild` from `discord-api-types`
> 
> 2. **`GuildMember`** - Guild member structure
>    - Properties: `userId`, `nick`, `avatar`, `roles`, `joinedAt`, `premiumSince`, `deaf`, `mute`, `flags`, `pending`, `permissions`, `communicationDisabledUntil`, `avatarDecorationData`
>    - Use `APIGuildMember` from `discord-api-types`
> 
> 3. **`Role`** - Role structure  
>    - Properties: `id`, `name`, `color`, `hoist`, `icon`, `unicodeEmoji`, `position`, `permissions`, `managed`, `mentionable`, `tags`, `flags`
>    - Use `APIRole` from `discord-api-types`
> 
> 4. **`GuildEmoji`** - Guild emoji structure
>    - Properties: `id`, `name`, `roles`, `user`, `requireColons`, `managed`, `animated`, `available`
>    - Use `APIEmoji` from `discord-api-types`
> 
> 5. **`GuildBan`** - Guild ban structure
>    - Properties: `reason`, `user`
>    - Use `APIBan` from `discord-api-types`
> 
> 6. **`RoleTags`** - Role tags structure
>    - Properties: `botId`, `integrationId`, `premiumSubscriber`, `subscriptionListingId`, `availableForPurchase`, `guildConnections`
>    - Use `APIRoleTags` from `discord-api-types`
> 
> 7. **`WelcomeScreen`** - Guild welcome screen structure
>    - Properties: `description`, `welcomeChannels`
>    - Use `APIGuildWelcomeScreen` from `discord-api-types`
> 
> 8. **`WelcomeChannel`** - Welcome screen channel structure
>    - Properties: `channelId`, `description`, `emojiId`, `emojiName`
>    - Use `APIGuildWelcomeScreenChannel` from `discord-api-types`
> 
> ### Additional Bitfields
> 
> 1. **`GuildMemberFlagsBitField`** - Using `GuildMemberFlags` from `discord-api-types`
> 2. **`RoleFlagsBitField`** - Using `RoleFlags` from `discord-api-types`
> 3. **`UserFlagsBitField`** - Using `UserFlags` from `discord-api-types`
> 4. **`SystemChannelFlagsBitField`** - Using `GuildSystemChannelFlags` from `discord-api-types`
> 5. **`GuildFlagsBitField`** - Using `GuildFeature` flags (if applicable)
> 
> ## Implementation Guidelines
> 
> 1. **Follow existing patterns** - Use the same structure as existing files in `packages/structures/src/`
> 2. **Extend `Structure` base class** - All structures should extend `Structure<APIType, OmittedKeys>`
> 3. **Use data templates** - Implement `DataTemplate` for optimized data storage where appropriate
> 4. **Implement `optimizeData`** - For timestamp fields and other optimizable data
> 5. **Use `discord-api-types`** - Import types from `discord-api-types/v10`
> 6. **Add proper JSDoc** - Document all public properties and methods
> 7. **Export from index** - Add new structures to `packages/structures/src/index.ts`
> 8. **Create `guilds/` folder** - Organize guild structures in `packages/structures/src/guilds/`
> 
> ## File Structure
> 
> ```
> packages/structures/src/
> ├── guilds/
> │   ├── index.ts
> │   ├── Guild.ts
> │   ├── GuildMember.ts
> │   ├── Role.ts
> │   ├── RoleTags.ts
> │   ├── GuildEmoji.ts
> │   ├── GuildBan.ts
> │   ├── WelcomeScreen.ts
> │   └── WelcomeChannel.ts
> ├── bitfields/
> │   ├── ... (existing)
> │   ├── GuildMemberFlagsBitField.ts
> │   ├── RoleFlagsBitField.ts
> │   ├── UserFlagsBitField.ts
> │   └── SystemChannelFlagsBitField.ts
> └── index.ts (updated to export guilds/)
> ```
> 
> ## Example Implementation Pattern
> 
> Based on existing structures like `User.ts`:
> 
> ```typescript
> import type { APIGuild } from 'discord-api-types/v10';
> import { Structure } from '../Structure.js';
> import { kData } from '../utils/symbols.js';
> import { toTimestamp, type TimestampResolvable } from '../utils/optimization.js';
> 
> type GuildOmittedKeys = '';
> 
> export class Guild extends Structure<APIGuild, GuildOmittedKeys> {
>   protected static override readonly DataTemplate: Partial<APIGuild> = {};
> 
>   public constructor(data: Readonly<Partial<APIGuild>>) {
>     super(data);
>     this.optimizeData(data);
>   }
> 
>   public get id() {
>     return this[kData].id;
>   }
> 
>   public get name() {
>     return this[kData].name;
>   }
> 
>   // ... other getters
> 
>   public override toJSON(): APIGuild {
>     return {
>       ...this[kData],
>     } as APIGuild;
>   }
> }
> ```
> 
> ## Testing
> 
> - Add tests in `packages/structures/__tests__/` following existing test patterns
> - Test structure creation, patching, cloning, and toJSON
> 
> ## References
> 
> - Existing structures: https://github.com/discordjs/discord.js/tree/main/packages/structures/src
> - Discord API Types: https://discord-api-types.dev/
> - Base Structure class: https://github.com/discordjs/discord.js/blob/main/packages/structures/src/Structure.ts
> 

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

📝 Walkthrough

Walkthrough

This PR introduces comprehensive implementations for Discord guild-related structures and specialized bitfield classes. It adds four new bitfield wrapper classes (GuildMemberFlagsBitField, RoleFlagsBitField, UserFlagsBitField, SystemChannelFlagsBitField) and eight guild structure classes (Guild, GuildMember, Role, RoleTags, GuildEmoji, GuildBan, WelcomeChannel, WelcomeScreen) with full test coverage for both. All changes extend existing base classes and expose property getters mapping to underlying raw data.

Changes

Cohort / File(s) Summary
Bitfield Wrapper Classes
packages/structures/src/bitfields/GuildMemberFlagsBitField.ts, RoleFlagsBitField.ts, UserFlagsBitField.ts, SystemChannelFlagsBitField.ts
Four new bitfield wrapper classes extending BitField<keyof typeof \*Flags>. Each exports a static Flags property and overrides toJSON() to delegate to super.toJSON(true).
Guild Structure Classes
packages/structures/src/guilds/Guild.ts, GuildMember.ts, Role.ts, RoleTags.ts, GuildEmoji.ts, GuildBan.ts, WelcomeChannel.ts, WelcomeScreen.ts
Eight new abstract structure classes extending Structure<API\*, Omitted> with static DataTemplate, constructors, and read-only getters for Discord API properties. GuildMember includes timestamp optimization and serialization logic.
Index Exports
packages/structures/src/bitfields/index.ts, packages/structures/src/guilds/index.ts, packages/structures/src/index.ts
Re-exports for four bitfield classes and eight guild classes added to module indices.
Bitfield Tests
packages/structures/__tests__/bitfields.test.ts
Comprehensive test suite covering GuildMemberFlagsBitField, RoleFlagsBitField, UserFlagsBitField, and SystemChannelFlagsBitField. Validates construction, add/remove operations, serialization, and flag presence checks.
Guild Tests
packages/structures/__tests__/guilds.test.ts
Test suite covering Guild, GuildMember, Role, RoleTags, GuildEmoji, GuildBan, WelcomeChannel, and WelcomeScreen. Validates core properties, timestamp handling, and JSON conversions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • High file count with repetitive patterns: Four nearly identical bitfield implementations and eight similarly structured guild classes with consistent getter patterns reduce cognitive load despite the quantity.
  • GuildMember complexity: The timestamp optimization logic (optimizeData method converting ISO timestamps to internal numbers and toJSON for serialization) warrants closer inspection.
  • Data mapping consistency: Review should verify consistent use of kData symbol and Partialize typing across all structure classes.
  • Test coverage adequacy: Verify tests sufficiently cover the timestamp conversion in GuildMember and the add/remove flag operations in bitfield tests.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding Guild structures and bitfields to the structures package.
Description check ✅ Passed The description is detailed and comprehensive, covering structures added, implementation notes, usage examples, and testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/add-guild-structures

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link

vercel bot commented Dec 9, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
discord-js Skipped Skipped Dec 9, 2025 10:24pm
discord-js-guide Skipped Skipped Dec 9, 2025 10:24pm

@vercel vercel bot temporarily deployed to Preview – discord-js-guide December 9, 2025 21:58 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js December 9, 2025 21:58 Inactive
Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview – discord-js-guide December 9, 2025 22:14 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js December 9, 2025 22:14 Inactive
Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview – discord-js December 9, 2025 22:20 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide December 9, 2025 22:20 Inactive
Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview – discord-js-guide December 9, 2025 22:24 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js December 9, 2025 22:24 Inactive
Copilot AI changed the title [WIP] Add guild-related structures to @discordjs/structures package Add Guild structures and additional bitfields to @discordjs/structures Dec 9, 2025
Copilot AI requested a review from iCrawl December 9, 2025 22:29
@iCrawl iCrawl changed the title Add Guild structures and additional bitfields to @discordjs/structures feat(structures): add Guild structures and additional bitfields to @discordjs/structures Dec 9, 2025
@codecov
Copy link

codecov bot commented Dec 9, 2025

Codecov Report

❌ Patch coverage is 63.59649% with 83 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.12%. Comparing base (548d752) to head (7cb61a1).

Files with missing lines Patch % Lines
packages/structures/src/guilds/Guild.ts 26.02% 54 Missing ⚠️
packages/structures/src/guilds/GuildMember.ts 66.12% 12 Missing and 9 partials ⚠️
packages/structures/src/guilds/Role.ts 78.57% 6 Missing ⚠️
packages/structures/src/guilds/RoleTags.ts 86.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11355      +/-   ##
==========================================
+ Coverage   32.45%   33.12%   +0.67%     
==========================================
  Files         369      381      +12     
  Lines       13612    13840     +228     
  Branches     1069     1081      +12     
==========================================
+ Hits         4418     4585     +167     
- Misses       9059     9108      +49     
- Partials      135      147      +12     
Flag Coverage Δ
structures 50.37% <63.59%> (+4.74%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@iCrawl
Copy link
Member

iCrawl commented Dec 9, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 548d752 and 7cb61a1.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (17)
  • packages/structures/__tests__/bitfields.test.ts (1 hunks)
  • packages/structures/__tests__/guilds.test.ts (1 hunks)
  • packages/structures/src/bitfields/GuildMemberFlagsBitField.ts (1 hunks)
  • packages/structures/src/bitfields/RoleFlagsBitField.ts (1 hunks)
  • packages/structures/src/bitfields/SystemChannelFlagsBitField.ts (1 hunks)
  • packages/structures/src/bitfields/UserFlagsBitField.ts (1 hunks)
  • packages/structures/src/bitfields/index.ts (1 hunks)
  • packages/structures/src/guilds/Guild.ts (1 hunks)
  • packages/structures/src/guilds/GuildBan.ts (1 hunks)
  • packages/structures/src/guilds/GuildEmoji.ts (1 hunks)
  • packages/structures/src/guilds/GuildMember.ts (1 hunks)
  • packages/structures/src/guilds/Role.ts (1 hunks)
  • packages/structures/src/guilds/RoleTags.ts (1 hunks)
  • packages/structures/src/guilds/WelcomeChannel.ts (1 hunks)
  • packages/structures/src/guilds/WelcomeScreen.ts (1 hunks)
  • packages/structures/src/guilds/index.ts (1 hunks)
  • packages/structures/src/index.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (12)
packages/structures/src/bitfields/SystemChannelFlagsBitField.ts (1)
packages/discord.js/typings/index.d.ts (1)
  • BitField (663-680)
packages/structures/src/guilds/WelcomeScreen.ts (2)
packages/discord.js/typings/index.d.ts (1)
  • WelcomeScreen (3910-3916)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/__tests__/guilds.test.ts (3)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/guilds/GuildMember.ts (1)
  • joinedAt (75-78)
packages/structures/src/guilds/RoleTags.ts (1)
  • RoleTags (11-65)
packages/structures/src/guilds/Role.ts (2)
packages/discord.js/typings/index.d.ts (1)
  • Role (2944-2984)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/guilds/WelcomeChannel.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/guilds/GuildBan.ts (2)
packages/discord.js/typings/index.d.ts (1)
  • GuildBan (1559-1566)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/bitfields/UserFlagsBitField.ts (1)
packages/discord.js/typings/index.d.ts (1)
  • BitField (663-680)
packages/structures/src/bitfields/RoleFlagsBitField.ts (1)
packages/discord.js/typings/index.d.ts (1)
  • BitField (663-680)
packages/structures/src/guilds/RoleTags.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/guilds/GuildMember.ts (2)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/utils/optimization.ts (1)
  • dateToDiscordISOTimestamp (20-22)
packages/structures/src/guilds/Guild.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/guilds/GuildEmoji.ts (2)
packages/discord.js/typings/index.d.ts (1)
  • GuildEmoji (1606-1619)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
🔇 Additional comments (26)
packages/structures/src/guilds/Role.ts (2)

1-23: LGTM on class structure and imports.

The abstract class follows the established pattern with proper generic constraints, DataTemplate, and constructor delegation to the base Structure class.


25-100: LGTM on property getters.

All getters correctly map to their corresponding APIRole fields via kData, following the established accessor pattern.

packages/structures/src/guilds/GuildMember.ts (4)

1-27: LGTM on imports, type definitions, and DataTemplate.

The GuildMemberOmittedKeys type correctly identifies the timestamp fields to be optimized. The DataTemplate with no-op setters is a clever pattern to prevent storing raw timestamp strings while allowing the optimization logic to handle them.


29-35: LGTM on constructor.

The constructor correctly delegates to super() then calls optimizeData() to convert ISO timestamp strings to numeric values.


37-154: LGTM on property getters.

The getters correctly handle the optimized timestamp fields with appropriate type assertions. The isCommunicationDisabled logic properly checks that the timestamp exists and is in the future.


156-174: LGTM on optimizeData implementation.

The method correctly handles the nullable timestamp fields by checking both undefined and null before conversion, and stores the numeric timestamps in appropriately named internal fields.

packages/structures/src/guilds/Guild.ts (2)

1-23: LGTM on class structure.

The abstract Guild class follows the established pattern with proper documentation noting the substructures that extending classes need to handle.


25-268: LGTM on property getters.

All 30+ getters correctly map to their corresponding APIGuild fields with appropriate camelCase naming conventions.

packages/structures/src/index.ts (1)

3-3: LGTM on guilds module export.

The re-export follows the established pattern and maintains alphabetical ordering.

packages/structures/__tests__/guilds.test.ts (5)

1-32: LGTM on imports.

All necessary types and structures are imported correctly for comprehensive testing.


34-115: LGTM on Guild tests.

Good coverage of essential properties. The as any cast on line 64 for preferred_locale is acceptable for test data.


194-247: LGTM on Role tests.

Good coverage including the hexColor computed property verification.


249-288: LGTM on RoleTags tests.

Good coverage of the various tag types and their presence-based boolean semantics.


290-395: LGTM on remaining structure tests.

GuildEmoji, GuildBan, WelcomeChannel, and WelcomeScreen tests provide adequate coverage of their respective properties.

packages/structures/src/bitfields/GuildMemberFlagsBitField.ts (1)

1-16: GuildMemberFlagsBitField is consistent with existing BitField wrappers

The generic constraint, static Flags binding, and toJSON override all align with the expected pattern for enum-based bitfields. No issues from a correctness or API-shape perspective.

packages/structures/src/bitfields/SystemChannelFlagsBitField.ts (1)

1-16: SystemChannelFlagsBitField matches the shared BitField wrapper pattern

Implementation cleanly wires GuildSystemChannelFlags into BitField with a numeric toJSON override, consistent with the other bitfield helpers. No changes requested.

packages/structures/src/bitfields/index.ts (1)

3-10: New bitfield exports are correctly wired into the public surface

The additional exports cleanly expose the new bitfield classes alongside existing ones without changing prior behavior.

packages/structures/src/bitfields/UserFlagsBitField.ts (1)

1-16: UserFlagsBitField is a clean, symmetric wrapper

This follows the same pattern as the other flag bitfields (generic key type, static Flags, numeric toJSON), keeping the API consistent. Looks good.

packages/structures/src/bitfields/RoleFlagsBitField.ts (1)

1-16: RoleFlagsBitField correctly wires RoleFlags into BitField

The class shape and toJSON override match the other flag wrappers, so behavior should be predictable and uniform across bitfield types.

packages/structures/src/guilds/GuildBan.ts (1)

1-31: GuildBan base structure is minimal and extensible as intended

The abstract GuildBan cleanly forwards raw API data into Structure, exposes reason from kData, and leaves DataTemplate plus the User substructure to concrete subclasses. This matches the documented design and doesn’t introduce obvious type or runtime issues.

packages/structures/src/guilds/index.ts (1)

1-8: Guild structures barrel cleanly exposes the new types

The re-exports are comprehensive and make the guild-related structures easy to import without affecting existing consumers.

packages/structures/src/guilds/WelcomeChannel.ts (1)

27-53: No changes needed — emojiName and emojiId nullability is already correct

The underlying API fields emoji_id and emoji_name are always present (not optional) and are nullable (Snowflake | null and string | null respectively). They return null directly when the API provides null, so the JSDoc contract of "null if no emoji is set" is already fulfilled. No ?? null normalization is required; the current implementation is correct.

packages/structures/src/guilds/WelcomeScreen.ts (1)

6-34: LGTM!

The abstract class correctly implements the Structure pattern with proper generic constraints. The documentation clearly indicates that WelcomeChannel substructures need to be instantiated by extending classes, which is an appropriate design for maintaining flexibility.

packages/structures/src/guilds/GuildEmoji.ts (1)

6-73: LGTM!

The abstract class correctly wraps APIEmoji data with properly documented getters. The snake_case to camelCase mapping (e.g., require_colonsrequireColons) follows TypeScript conventions. The documentation appropriately notes that the User substructure needs to be handled by extending classes.

packages/structures/src/guilds/RoleTags.ts (1)

38-64: LGTM!

The boolean getters (premiumSubscriber, availableForPurchase, guildConnections) correctly implement Discord's sentinel field pattern where the presence of the key (regardless of value) indicates true. Using !== undefined properly handles this API behavior.

packages/structures/__tests__/bitfields.test.ts (1)

1-204: Good test coverage for bitfield operations.

The test suite comprehensively covers the core operations (construction, add, remove, has, serialize, toJSON) for all four bitfield classes. The tests correctly use the flag enums from discord-api-types/v10.

Comment on lines +180 to +184
test('should correctly identify if communication is disabled', () => {
// The timestamp is in the future (2024-12-31), so it should be disabled
// But we're testing in 2025, so let's check the behavior
expect(typeof member.isCommunicationDisabled).toBe('boolean');
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Time-sensitive test may produce unexpected results.

The comment acknowledges that the test data uses a 2024 timestamp, but the test only checks typeof. Given the current date is December 2025, isCommunicationDisabled will always be false since the timeout has expired.

Consider either using a far-future date or explicitly asserting the expected false value:

 test('should correctly identify if communication is disabled', () => {
-  // The timestamp is in the future (2024-12-31), so it should be disabled
-  // But we're testing in 2025, so let's check the behavior
-  expect(typeof member.isCommunicationDisabled).toBe('boolean');
+  // The timestamp (2024-12-31) is in the past, so communication is not disabled
+  expect(member.isCommunicationDisabled).toBe(false);
 });

Or use a far-future timestamp in the test data to ensure consistent behavior.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('should correctly identify if communication is disabled', () => {
// The timestamp is in the future (2024-12-31), so it should be disabled
// But we're testing in 2025, so let's check the behavior
expect(typeof member.isCommunicationDisabled).toBe('boolean');
});
test('should correctly identify if communication is disabled', () => {
// The timestamp (2024-12-31) is in the past, so communication is not disabled
expect(member.isCommunicationDisabled).toBe(false);
});
🤖 Prompt for AI Agents
In packages/structures/__tests__/guilds.test.ts around lines 180 to 184, the
test uses a 2024 timestamp and only asserts typeof
member.isCommunicationDisabled, which is time-sensitive and will be false in
2025; either update the fixture to use a far-future timestamp (e.g., year 9999)
so isCommunicationDisabled is consistently true and assert the expected boolean,
or explicitly assert the current expected value
(expect(member.isCommunicationDisabled).toBe(false)) to reflect the expired
timeout.

Comment on lines +176 to +195
public override toJSON(): APIGuildMember {
const data = { ...this[kData] } as APIGuildMember;

const joinedTimestamp = this.joinedTimestamp;
if (joinedTimestamp !== null) {
data.joined_at = dateToDiscordISOTimestamp(new Date(joinedTimestamp));
}

const premiumSinceTimestamp = this.premiumSinceTimestamp;
if (premiumSinceTimestamp !== null) {
data.premium_since = dateToDiscordISOTimestamp(new Date(premiumSinceTimestamp));
}

const communicationDisabledUntilTimestamp = this.communicationDisabledUntilTimestamp;
if (communicationDisabledUntilTimestamp !== null) {
data.communication_disabled_until = dateToDiscordISOTimestamp(new Date(communicationDisabledUntilTimestamp));
}

return data;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Internal timestamp fields leak into JSON output.

The spread { ...this[kData] } copies the internal *_timestamp fields (e.g., joined_at_timestamp) into the JSON output. These aren't part of APIGuildMember and may cause issues if the JSON is sent back to Discord's API or compared for equality.

Consider deleting the internal fields from the output:

 public override toJSON(): APIGuildMember {
   const data = { ...this[kData] } as APIGuildMember;
+  // Remove internal optimization fields
+  delete (data as Record<string, unknown>).joined_at_timestamp;
+  delete (data as Record<string, unknown>).premium_since_timestamp;
+  delete (data as Record<string, unknown>).communication_disabled_until_timestamp;

   const joinedTimestamp = this.joinedTimestamp;
   if (joinedTimestamp !== null) {
     data.joined_at = dateToDiscordISOTimestamp(new Date(joinedTimestamp));
   }
🤖 Prompt for AI Agents
In packages/structures/src/guilds/GuildMember.ts around lines 176 to 195, the
spread of this[kData] into the APIGuildMember output leaks internal timestamp
fields (e.g., joined_at_timestamp, premium_since_timestamp,
communication_disabled_until_timestamp) that are not part of APIGuildMember;
remove those internal keys from the copied data object after spreading and
before returning (delete the *_timestamp properties or filter them out) so only
the correct API fields (joined_at, premium_since, communication_disabled_until)
remain in the returned JSON.

Comment on lines +105 to +108
public get hexColor() {
const color = this.color as number;
return `#${color.toString(16).padStart(6, '0')}`;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Unnecessary type assertion.

The color getter already returns a number from APIRole, so the as number cast is redundant.

 public get hexColor() {
-  const color = this.color as number;
-  return `#${color.toString(16).padStart(6, '0')}`;
+  return `#${this.color.toString(16).padStart(6, '0')}`;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public get hexColor() {
const color = this.color as number;
return `#${color.toString(16).padStart(6, '0')}`;
}
public get hexColor() {
return `#${this.color.toString(16).padStart(6, '0')}`;
}
🤖 Prompt for AI Agents
In packages/structures/src/guilds/Role.ts around lines 105 to 108, remove the
redundant "as number" type assertion in the hexColor getter; assign const color
= this.color; and keep the rest of the logic unchanged (format color to hex with
toString(16).padStart(6, '0') and prefix with '#').

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants