Repository navigation
feat(plugin-gateway): add ClientApplication and client.application - #238
Conversation
Add the Application, ClientApplication, Team and TeamMember structures, like discord.js. client.application is built from clientId when the client is, so it exists before READY (partial); READY patches the same instance with the flags and fetch() with the rest. Also add fetch, edit and the role connection metadata methods. Refs #208
|
Nothing flagged · reviewed Architecture Inside the changed components — 2 viewsComponent view — Client Application Lifecycle Lifecycle, event patching, and API synchronization of ClientApplication within Gateway Client Component view — Application Ownership and Teams Team and member domain structures modeling application ownership Data flow Tip The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change 🪧 More tips
Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
There was a problem hiding this comment.
ℹ️ No critical issues — one minor suggestion inline.
Reviewed changes
Reviewed the full diff of the single commit, and checked the @discordjs/core and @discordjs/rest typings the new code calls.
client.application: built in theGatewayClientconstructor from the client ID, so it exists beforeREADY, andREADYpatches the same instance in place.ClientApplication/Application: partial-aware getters,fetch(),edit()(images throughresolveImageOption), and role connection metadata records with camelCased fields.Team/TeamMember: memoized per payload, withownerthe team'sTeamMemberwhen it is among the members.- Tests, docs, changeset:
tests/applications.test.ts, a type-level test, the README section and aminorchangeset.
getCurrent, editCurrent, getMetadataRecords, updateMetadataRecords, CDN#appIcon and CDN#teamIcon all exist in the installed typings, and the shallow-merge kPatch matches how READY (id and flags only) is applied. I found no correctness problems.
claude-sonnet-5-5 | 𝕏
The owner Team, its members and their users were not bound to the client that built them, so their client fell back to the most recently constructed GatewayClient. Bind the team like the owner user, and have Team#members pass the client on to each TeamMember.
@wolfstar/plugin-api
@wolfstar/plugin-broker
@wolfstar/plugin-cache
@wolfstar/plugin-gateway
@wolfstar/plugin-i18next
@wolfstar/plugin-logger
@wolfstar/plugin-scheduled-tasks
@wolfstar/plugin-sharder
@wolfstar/plugin-subcommands-advanced
commit: |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the incremental commit since the prior pullfrog review (11f7e3b).
- Owner bound to the client:
ClientApplication#ownernow binds both theTeamand the ownerUserto the client withbindClient. - Members bound to the client:
Team#memberspasseskClienton to eachTeamMember, soTeamMember#useris bound too. - Test coverage: the team application test asserts
.client === clienton the application, its owner and the owner's user.
claude-sonnet-5-5 | 𝕏

🔗 Linked issue
Resolves #208
🧭 Context
@wolfstar/plugin-gatewayhad noApplication/ClientApplication, so there was noclient.application. In discord.js it is the entry point for everything the application owns rather than a guild, and #207 (ApplicationEmoji,ApplicationCommandand their managers) cannot land without it. This is that prerequisite on its own.📚 Description
Adds
client.application, aClientApplicationmodeled on discord.js's, plus theApplication,TeamandTeamMemberstructures it needs.client.applicationis built in theGatewayClientconstructor fromclientId, so it exists beforeREADYand without a gateway connection. It ispartial(onlyidknown) untilfetch()oredit()resolves.READYpatches the same instance in place with the application'sflags, so references held by user code stay valid, and broker workers that never seeREADYstill have it.@wolfstar/plugin-cache: it is one small object per client, has no gateway update event, and every process gets the sameREADY.owneris theTeam(members asTeamMembers) when a team owns the application, the ownerUserbound to the client otherwise.fetch()(GET /applications/@me),edit()(PATCH /applications/@me, images throughresolveImageOption),fetchRoleConnectionMetadataRecords()andeditRoleConnectionMetadataRecords(), with camelCased records like discord.js.commands/emojis/entitlementsproperties: plugin-gateway: port ApplicationEmoji (with its manager) and ApplicationCommand (discord.js parity) #207 and the entitlements work add those getters themselves.Departures from the Pullfrog plan, and from discord.js:
client.applicationis typed non-null, discord.js types it nullable. This follows the plan (clientIdis a required option) and is a superset of discord.js's behavior. The three open points of the plan (non-null application,Team/TeamMembershipped here, cache stays on the client) were taken as recommended.Application#nameisstring | null(andtoString()falls back to the id) because the partial application has no name.@wolfstar/http-frameworkexposes the public key. It is not needed: nothing here uses it, andverify_keystays available fromfetch()through the raw data.Key changes
structures/applications/Application,ClientApplication,Team,TeamMember, exported from the packageGatewayClientreadonly application, built fromclientIdutil/dispatch.tsREADYpatchesclient.applicationin placetests/applications.test.ts(9 tests) andtests/types/application.tsminorchangeset for@wolfstar/plugin-gatewayVerification, run locally:
pnpm buildandpnpm typecheckpass,pnpm testpasses (121 files, 1688 tests).oxlintreports no errors andoxfmt --checkpasses on the files of this PR. The repo-widepnpm lintfailsoxfmt --checkon a Windows checkout only because its working-tree files are CRLF; I did not touch them.Type of Change
Pre-flight Checklist
pnpm changeset(orpnpm changeset add --emptyif no release is needed). See .changeset/README.md.