Skip to content

feat(invite): new endpoints and target users file and roles#11392

Draft
imnaiyar wants to merge 5 commits intodiscordjs:mainfrom
imnaiyar:feat/new-invites
Draft

feat(invite): new endpoints and target users file and roles#11392
imnaiyar wants to merge 5 commits intodiscordjs:mainfrom
imnaiyar:feat/new-invites

Conversation

@imnaiyar
Copy link
Contributor

@vercel
Copy link

vercel bot commented Jan 22, 2026

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

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
discord-js Skipped Skipped Feb 24, 2026 5:21pm
discord-js-guide Skipped Skipped Feb 24, 2026 5:21pm

Request Review

@vercel vercel bot temporarily deployed to Preview – discord-js-guide January 22, 2026 18:47 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js January 22, 2026 18:47 Inactive
@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

This PR introduces target users management for Guild Invites. It adds new parameters to invite creation (roles, targetUsersFile), implements methods to fetch and update target users via FormData, retrieves job status for async user processing, and adds corresponding TypeScript definitions across multiple files.

Changes

Cohort / File(s) Summary
Core Invite Manager Implementation
packages/discord.js/src/managers/GuildInviteManager.js
Extended create() method with roles and targetUsersFile parameters. Added three public methods (fetchTargetUsers, updateTargetUsers, fetchTargetUsersJobStatus) to manage target users. Introduced private _createInviteFormData() helper to construct FormData payloads for file uploads. Conditional FormData/JSON body handling based on file presence.
Invite Structure & Delegation
packages/discord.js/src/structures/GuildInvite.js
Added roles property (Collection or null) populated during _patch(). Introduced three convenience methods that delegate to GuildInviteManager equivalents. Updated toJSON() to include roles in serialized output.
Type Definitions
packages/discord.js/typings/index.d.ts
Imported InviteTargetUsersJobStatus from discord-api-types. Extended GuildInvite with roles property and new methods. Extended GuildInviteManager with target users management methods. Expanded InviteCreateOptions with roles and targetUsersFile fields. Added new TargetUsersJobStatusForInvite interface with status tracking fields.
Documentation & JSDoc
packages/discord.js/src/structures/BaseGuildTextChannel.js, packages/discord.js/src/util/APITypes.js
Updated InviteCreateOptions typedef with targetUsersFile and roles properties. Added external documentation block for InviteTargetUsersJobStatus API type.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GuildInvite
    participant GuildInviteManager
    participant Discord API

    Client->>GuildInvite: updateTargetUsers(targetUsersFile)
    GuildInvite->>GuildInviteManager: updateTargetUsers(code, targetUsersFile)
    GuildInviteManager->>GuildInviteManager: _createInviteFormData(targetUsersFile)
    Note over GuildInviteManager: Resolve file/array to CSV<br/>Build FormData payload
    GuildInviteManager->>Discord API: POST with FormData
    Discord API-->>GuildInviteManager: Job queued
    GuildInviteManager-->>GuildInvite: Promise<unknown>
    GuildInvite-->>Client: Result

    Client->>GuildInvite: fetchTargetUsersJobStatus()
    GuildInvite->>GuildInviteManager: fetchTargetUsersJobStatus(code)
    GuildInviteManager->>Discord API: GET job status
    Discord API-->>GuildInviteManager: Status object
    GuildInviteManager-->>Client: TargetUsersJobStatusForInvite
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: adding new invite endpoints and support for target users file and roles management.
Description check ✅ Passed The description provides context by referencing a dependency PR, which is directly related to implementing the invite functionality changes in this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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: 5

🤖 Fix all issues with AI agents
In `@packages/discord.js/src/managers/GuildInviteManager.js`:
- Around line 266-313: The JSDoc return types are wrong for the async methods:
change fetchTargetUsers' `@returns` from {Buffer} to {Promise<Buffer>}, change
fetchTargetUsersJobStatus' `@returns` from {TargetUsersJobStatusForInvite[]}
(array) to {Promise<TargetUsersJobStatusForInvite>}, and ensure
updateTargetUsers (async) documents its return as {Promise<unknown>} if kept;
update the JSDoc comments above the functions fetchTargetUsers,
updateTargetUsers, and fetchTargetUsersJobStatus to reflect these Promise<>
return types.
- Around line 232-240: The current construction of options for invite creation
(in GuildInviteManager.js where options.role_ids is built from roles?.map(role
=> this.guild.roles.resolveId(role))) can include null entries which cause API
400s; update the logic that builds role_ids to either filter out falsy/null
resolved IDs (e.g., roles?.map(...).filter(Boolean)) or validate/throw if any
role fails to resolve so you never send nulls to the API, keeping references to
role_ids and this.guild.roles.resolveId in your change.
- Around line 322-334: In _createInviteFormData, filter out unresolved user IDs
returned by this.client.users.resolveId when handling an array targetUsersFile
so the CSV doesn't contain "null" entries; replace the current map(...).join
with a map -> filter(Boolean) -> join('\n') pipeline and if the resulting
usersCsv is empty either throw a clear error or handle it consistently (e.g.,
reject the request) before appending the Blob and payload_json to the FormData.

In `@packages/discord.js/src/structures/GuildInvite.js`:
- Around line 222-228: The JSDoc for the "Update target users of this invite"
method in GuildInvite.js has a typo in the `@returns` type — change
"Promes<unknown>" to "Promise<unknown>" in the JSDoc block above the
update-target-users method (the JSDoc attached to the GuildInvite update
function) so the return type is correctly documented.
- Around line 184-191: The roles Collection for GuildInvite is being constructed
with each Role instantiated from the whole invite payload (new Role(this.client,
data, this.guild)), causing mismatched fields; change the constructor to use the
individual role payload (use the loop variable, e.g., role) so each entry is new
Role(this.client, role, this.guild) and the Collection key remains consistent
with role.id in the roles assignment inside the GuildInvite class.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 838cd2d and f39589b.

📒 Files selected for processing (5)
  • packages/discord.js/src/managers/GuildInviteManager.js
  • packages/discord.js/src/structures/BaseGuildTextChannel.js
  • packages/discord.js/src/structures/GuildInvite.js
  • packages/discord.js/src/util/APITypes.js
  • packages/discord.js/typings/index.d.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/discord.js/src/structures/GuildInvite.js (2)
packages/discord.js/src/managers/GuildInviteManager.js (7)
  • require (3-3)
  • require (4-4)
  • require (5-5)
  • require (6-6)
  • require (7-7)
  • require (8-8)
  • require (9-9)
packages/discord.js/typings/index.d.ts (2)
  • Collection (1084-1084)
  • Role (2965-3005)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests
🔇 Additional comments (8)
packages/discord.js/src/util/APITypes.js (1)

522-526: Doc addition looks good.
Clear external reference for the new enum.

packages/discord.js/src/structures/BaseGuildTextChannel.js (1)

164-166: InviteCreateOptions docs are clear and consistent.
No issues found.

packages/discord.js/src/structures/GuildInvite.js (2)

3-3: Required imports added for new roles support.

Also applies to: 11-11


261-261: Serialization update is appropriate.

packages/discord.js/typings/index.d.ts (2)

2064-2077: Type additions align with the new invite target-users API.

The roles/targetUsersFile options, job-status type, and manager method signatures are coherent.

Also applies to: 4521-4543, 6605-6610


163-166: Verify that discord-api-types 0.38.36 exports InviteTargetUsersJobStatus.

The import is present in the typings file and the type is actively used (line 165, also used in a type definition with status: InviteTargetUsersJobStatus). However, web searches did not confirm that InviteTargetUsersJobStatus is available in discord-api-types v0.38.36. The package.json specifies ^0.38.36, but the symbol's availability in this version could not be verified from available documentation or changelogs. Confirm the dependency version includes this export, or bump to the version that includes the required symbol.

packages/discord.js/src/managers/GuildInviteManager.js (2)

3-8: Import updates look good.


107-117: Typedef shape is clear.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +232 to +240
const options = {
temporary,
max_age: maxAge,
max_uses: maxUses,
unique,
target_user_id: this.client.users.resolveId(targetUser),
target_application_id: targetApplication?.id ?? targetApplication?.applicationId ?? targetApplication,
role_ids: roles?.map(role => this.guild.roles.resolveId(role)),
target_type: targetType,
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

Avoid serializing unresolved role IDs.

roles?.map(...resolveId) can yield null, which becomes null entries in role_ids and can trigger 400s from the API. Filter (or fail fast) before POST.

Proposed fix (filter unresolved IDs)
-      role_ids: roles?.map(role => this.guild.roles.resolveId(role)),
+      role_ids: roles
+        ?.map(role => this.guild.roles.resolveId(role))
+        .filter(Boolean),
🤖 Prompt for AI Agents
In `@packages/discord.js/src/managers/GuildInviteManager.js` around lines 232 -
240, The current construction of options for invite creation (in
GuildInviteManager.js where options.role_ids is built from roles?.map(role =>
this.guild.roles.resolveId(role))) can include null entries which cause API
400s; update the logic that builds role_ids to either filter out falsy/null
resolved IDs (e.g., roles?.map(...).filter(Boolean)) or validate/throw if any
role fails to resolve so you never send nulls to the API, keeping references to
role_ids and this.guild.roles.resolveId in your change.

Comment on lines +322 to +334
async _createInviteFormData({ targetUsersFile, ...rest } = {}) {
const formData = new FormData();
let usersCsv;
if (Array.isArray(targetUsersFile)) {
usersCsv = targetUsersFile.map(user => this.client.users.resolveId(user)).join('\n');
} else {
const resolved = await resolveFile(targetUsersFile);
usersCsv = resolved.data.toString('utf8');
}

formData.append('target_users_file', new Blob([usersCsv], { type: 'text/csv' }), 'users.csv');
formData.append('payload_json', JSON.stringify(rest));
return formData;
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check Node engine requirement
echo "=== Node Engine Requirement ==="
rg -n "engines" packages/discord.js/package.json

echo -e "\n=== FormData/Blob usage in discord.js src ==="
rg -n "FormData\|Blob" packages/discord.js/src

echo -e "\n=== FormData/Blob imports ==="
rg -n "import.*FormData\|import.*Blob\|require.*FormData\|require.*Blob" packages/discord.js/src

echo -e "\n=== undici or polyfill usage ==="
rg -n "undici\|formdata" packages/discord.js/src

Repository: discordjs/discord.js

Length of output: 226


🏁 Script executed:

#!/bin/bash
# Locate and examine resolveId function
echo "=== Finding resolveId implementation ==="
rg -n "resolveId" packages/discord.js/src -A 5 -B 2 | head -100

Repository: discordjs/discord.js

Length of output: 9356


🏁 Script executed:

#!/bin/bash
# Check package.json dependencies for any polyfills
echo "=== Checking for polyfill dependencies ==="
cat packages/discord.js/package.json | jq '.dependencies, .devDependencies' | grep -i "form\|blob\|fetch\|undici"

Repository: discordjs/discord.js

Length of output: 248


🏁 Script executed:

#!/bin/bash
# Get the full engines object from package.json
echo "=== Full engines requirement ==="
cat packages/discord.js/package.json | jq '.engines'

echo -e "\n=== Check GuildInviteManager.js for imports ==="
head -50 packages/discord.js/src/managers/GuildInviteManager.js

Repository: discordjs/discord.js

Length of output: 1479


🏁 Script executed:

#!/bin/bash
# Find BaseManager to understand resolveId behavior
echo "=== BaseManager resolveId implementation ==="
rg -n "class BaseManager" packages/discord.js/src -A 50 | head -100

echo -e "\n=== resolveId implementation in BaseManager ==="
rg -n "resolveId.*{" packages/discord.js/src/managers/BaseManager.js -A 5

Repository: discordjs/discord.js

Length of output: 1265


🏁 Script executed:

#!/bin/bash
# Get the full context of _createInviteFormData method
echo "=== Full _createInviteFormData method ==="
sed -n '322,334p' packages/discord.js/src/managers/GuildInviteManager.js

Repository: discordjs/discord.js

Length of output: 668


🏁 Script executed:

#!/bin/bash
# Find resolveId implementation in BaseManager or UserManager
echo "=== Find resolveId in BaseManager.js ==="
cat packages/discord.js/src/managers/BaseManager.js

echo -e "\n=== Find resolveId in UserManager.js ==="
rg -n "resolveId" packages/discord.js/src/managers/UserManager.js -A 8

Repository: discordjs/discord.js

Length of output: 1807


🏁 Script executed:

#!/bin/bash
# Search for FormData usage to see how it's imported/used across the codebase
echo "=== FormData usage in GuildInviteManager and vicinity ==="
grep -n "FormData\|new Blob" packages/discord.js/src/managers/GuildInviteManager.js

echo -e "\n=== Check if there are any imports for FormData at top of file ==="
head -20 packages/discord.js/src/managers/GuildInviteManager.js | grep -i "form\|blob\|import\|require"

Repository: discordjs/discord.js

Length of output: 1048


🏁 Script executed:

#!/bin/bash
# Get a better understanding of how resolveId behaves in UserManager
echo "=== UserManager resolve/resolveId methods ==="
rg -n "resolve\(" packages/discord.js/src/managers/UserManager.js -B 2 -A 8 | head -80

Repository: discordjs/discord.js

Length of output: 558


🏁 Script executed:

#!/bin/bash
# Check CachedManager and parent classes for the actual resolveId implementation
echo "=== CachedManager.js ==="
cat packages/discord.js/src/managers/CachedManager.js

echo -e "\n=== Check parent class chain in managers ==="
head -30 packages/discord.js/src/managers/CachedManager.js

Repository: discordjs/discord.js

Length of output: 2474


🏁 Script executed:

#!/bin/bash
# See how resolveId is actually implemented in the full chain
rg -n "class.*Manager extends" packages/discord.js/src/managers/CachedManager.js

echo -e "\n=== Look for the actual resolveId implementation ==="
rg -n "resolveId" packages/discord.js/src/managers/CachedManager.js -B 2 -A 6

Repository: discordjs/discord.js

Length of output: 162


🏁 Script executed:

#!/bin/bash
# Check DataManager.js for resolveId implementation
echo "=== DataManager.js ==="
cat packages/discord.js/src/managers/DataManager.js

Repository: discordjs/discord.js

Length of output: 1736


Filter out unresolved user IDs to prevent invalid entries in the CSV.

When resolveId returns null for unresolved users, the mapped array contains null values. Joining these with \n produces the string "null" in the CSV, which is not a valid user ID and can cause the API to reject or silently drop the request. Filter out falsy values to ensure only valid IDs are included.

FormData and Blob are available as stable globals in Node 22.12.0+ (the required minimum version), so no polyfill is needed.

Proposed fix
-      usersCsv = targetUsersFile.map(user => this.client.users.resolveId(user)).join('\n');
+      const userIds = targetUsersFile
+        .map(user => this.client.users.resolveId(user))
+        .filter(Boolean);
+      usersCsv = userIds.join('\n');
🤖 Prompt for AI Agents
In `@packages/discord.js/src/managers/GuildInviteManager.js` around lines 322 -
334, In _createInviteFormData, filter out unresolved user IDs returned by
this.client.users.resolveId when handling an array targetUsersFile so the CSV
doesn't contain "null" entries; replace the current map(...).join with a map ->
filter(Boolean) -> join('\n') pipeline and if the resulting usersCsv is empty
either throw a clear error or handle it consistently (e.g., reject the request)
before appending the Blob and payload_json to the FormData.

@vercel vercel bot temporarily deployed to Preview – discord-js January 22, 2026 19:26 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide January 22, 2026 19:26 Inactive
@Jiralite Jiralite marked this pull request as draft January 22, 2026 19:28
@vercel vercel bot temporarily deployed to Preview – discord-js February 24, 2026 17:21 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 24, 2026 17:21 Inactive
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.

1 participant