2026 Code Clean Up #487
Labels
No labels
blocked
duplicate
needs
approval
needs
criteria
needs
estimate
needs
tests
question
step
doing
step
review
step
testing
step
todo
step
uat
type
admin
type
alert
type
bug
type
change
type
defect
type
dependencies
type
epic
type
idea
type
incident
type
investigation
type
spike
type
story
wontfix
No project
No assignees
2 participants
Notifications
Total time spent: 12 minutes 54 seconds
Due date
Vylpes
12 minutes 54 seconds
No due date set.
Dependencies
No dependencies set
Reference
External/card-drop#487
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Story Points: 13
Scan the repository for areas of code which can be cleaned up and perhaps written a bit cleaner. Identify any major areas not covered by testing or documentation which should be.
Card Drop cleanup + coverage checklist
Actionable items from a 2026 repository scan. Check items off as they are completed.
Code cleanup
Rename misspelled
GuildMemebrUpdatetoGuildMemberUpdatesrc/contracts/EventExecutors.ts,src/client/client.ts,src/client/util.tsAwait async command / button / dropdown handlers in dispatchers
src/client/interactionCreate/Button.ts,src/client/interactionCreate/ChatInputCommand.ts,src/client/interactionCreate/StringDropdown.tsawait, so rejected promises bypass the surroundingtry/catch.await item.Event.execute(...)/await itemToUse.Command.execute(...).e as string; useAppLogger.CatchErroror similar).Throw
Errorobjects instead of bare stringssrc/bot.ts,src/client/appLogger.tsthrow "..."tothrow new Error("...")and keep logging consistent.Replace loose equality (
==/!=) with strict equality (===/!==)src/helpers/DropHelpers/GetUnclaimedCardsHelper.ts,src/helpers/InventoryHelper.ts,src/commands/sacrifice.ts,src/helpers/SeriesHelper.ts,src/helpers/TimerHelper.ts, and related helpers/commands that compare quantities/IDs.eqeqeqin ESLint, then fix remaining violations.Stop mutating source arrays during pagination
src/helpers/SeriesHelper.tssplicepage selection withsliceso cloned card lists are not mutated as a side effect.Stop swallowing image-generation errors
src/helpers/ImageHelper.tscatchwith a TODO currently drops failures. Capture the error, log it (or rethrow), and cover failure modes in tests.Fix
AppBaseEntity.FetchOneByIdrelations defaultsrc/contracts/AppBaseEntity.tsrelations || {}; TypeORM expects an array. Default torelations || [](same pattern asFetchAll).Harden timer tick execution
src/helpers/TimerHelper.tsonTickcallbacks and log tick failures.Add authentication to the reload webhook
src/webhooks.ts(POST /api/reload-db)Project metadata / dependency cleanup
package.jsonjest(and related test packages if appropriate) fromdependenciestodevDependencies.bugs.url(https//...→https://...).Testing gaps
Current Jest coverage is concentrated on drop/multidrop/effects commands, a subset of button events,
PurgeClaims, and a few helpers. Priority gaps:Add helper tests for uncovered helpers
src/helpers/InventoryHelper.tssrc/helpers/CardSearchHelper.tssrc/helpers/SeriesHelper.tssrc/helpers/DropHelpers/GetUnclaimedCardsHelper.tssrc/helpers/ImageHelper.tsAdd command tests for untested slash commands
daily,gdrivesync,give,inventory,resync,sacrifice,series,stats,trade,view,about,id, andstage/*.Add button-event tests for untested handlers
inventory,sacrifice,series,trade,view.Add string-dropdown coverage
src/stringDropdowns/Inventory.tsand dispatch path insrc/client/interactionCreate/StringDropdown.ts.Add webhook + middleware tests
src/webhooks.tssrc/client/interactionCreate/middleware/NewUserDiscovery.tsAdd timer coverage for
GiveCurrencysrc/timers/GiveCurrency.ts(onlyPurgeClaimsis tested today).Assert dispatcher error-handling after awaiting handlers
Documentation gaps
Expand README with developer ops
yarn test/yarn lint.db:upmention.POST /api/reload-db(and auth once added).Document how to add commands / button events / dropdown events
src/registry.tsand the interaction-create dispatchers so contributors know where to register new handlers.Cross-link existing docs to testing / env expectations
docs/cards.md,docs/google-drive-sync.md,docs/logger.mdshould reference where env vars live and what tests are expected when changing those areas.Suggested order of attack
await+ error logging (correctness).GuildMemebrUpdatetypo andAppBaseEntityrelations default.splicepagination and empty catch inImageHelper./api/reload-dband document it.inventory,sacrifice,trade,series,view).Estimate: 13 story points
The cleanup checklist is specific (files, behaviours, and order of attack), so this can be sized without going back to criteria.
Breakdown:
awaitin dispatchers,Errorthrows, strict equality,slicepagination,ImageHelpercatch,FetchOneByIdrelations default, timer ticks,package.json. The heavier piece is authenticatingPOST /api/reload-db.inventory,sacrifice,trade,series,view) plus buttons/dropdowns/webhooks/GiveCurrency. Remaining command tests are patterned Jest work, not new product behaviour.yarn test/yarn lint, migrations, reload webhook), how to register commands/events, and cross-links in existing docs.13 fits better than 8 (tests alone exceed that) or 21 (the work is repetitive, not exploratory).
Moving to
needs/tests.QA test scripts (against the cleanup + coverage checklist)
Preconditions for all scripts unless noted:
yarn testandyarn lintrun cleanly ondevelopbefore the change (baseline).TC-01 — GuildMemberUpdate typo rename
Covers: Rename
GuildMemebrUpdate→GuildMemberUpdateGuildMemebrUpdate— expect: zero matches.GuildMemberUpdateis registered inEventExecutors,client.ts, andutil.ts.Expect: the member-update handler still runs (no crash, no “unknown event” log). Existing member-update behaviour is unchanged.
TC-02 — Dispatcher await + error handling
Covers: Await command / button / dropdown handlers; rejected promises are caught
Expect: each interaction replies as today; no unhandled-rejection logs.
throw new Error("qa-dispatch")(or use a test double) for command, button, and dropdown paths.Expect: the dispatcher
try/catchlogs viaAppLogger.CatchError(or equivalent), the user gets the existing error reply, and the process does not crash.e as string.TC-03 — Throw Error objects
Covers:
src/bot.ts,src/client/appLogger.tsthrow "/throw 'in those files — expect: none.Expect: stack traces include a real
Error; logging still records the message.TC-04 — Strict equality
Covers: quantity/ID comparisons (
GetUnclaimedCardsHelper,InventoryHelper,sacrifice,SeriesHelper,TimerHelper, related files)eqeqeqis enabled (or no remaining==/!=in the listed files)./inventorywith 0, 1, and many cards;/sacrificewith valid and invalid quantities; series pagination; timer ticks.Expect: same user-visible results as before; no false matches from type-coercion (e.g.
"1"vs1).TC-05 — Series pagination does not mutate source
Covers:
SeriesHelpersplice→slice/seriespage 1, then page 2, then back to page 1 (repeat 3+ times).Expect: page 1 contents stay stable; card counts do not shrink.
TC-06 — ImageHelper errors are not swallowed
Covers: empty
catchinImageHelperExpect: the error is logged (or rethrown per implementation); it is not silently dropped.
TC-07 — FetchOneById relations default
Covers:
AppBaseEntity.FetchOneByIddefault[]not{}Expect: no TypeORM relations-type error; related rows load only when requested.
TC-08 — Timer tick hardening
Covers:
TimerHelperID lookup + asynconTickGiveCurrencyandPurgeClaimstick on schedule.Expect: ticks still fire; wrong IDs are not matched.
onTickrejection.Expect: the failure is logged; later ticks still run.
TC-09 — Reload webhook authentication
Covers:
POST /api/reload-dbauthPOST /api/reload-dbwith no auth header.Expect: 401/403; DB is not reloaded.
Expect: 401/403; no reload.
Expect: 2xx; DB reload occurs as today.
TC-10 — package.json cleanup
Covers: jest in
devDependencies;bugs.urlschemepackage.json.Expect:
jest(and related test packages if moved) are underdevDependencies;bugs.urlstarts withhttps://.yarn teststill runs from a fresh install of production+dev deps.TC-11 — Helper unit tests exist and pass
Covers: InventoryHelper, CardSearchHelper, SeriesHelper, GetUnclaimedCardsHelper, ImageHelper
yarn testincludes new/expanded suites for each helper.Expect: success, empty, and error/edge cases; ImageHelper includes a failure-mode test.
TC-12 — Command unit tests exist and pass
Covers:
daily,gdrivesync,give,inventory,resync,sacrifice,series,stats,trade,view,about,id,stage/*yarn testis green.TC-13 — Button, dropdown, webhook, middleware, timer tests
Covers: buttons
inventory/sacrifice/series/trade/view;stringDropdowns/Inventory;webhooks.ts;NewUserDiscovery;GiveCurrencyyarn testis green.TC-14 — Lint and full test suite
yarn lint— expect: 0 errors.yarn test— expect: 0 failures; coverage includes the new files (no requirement to hit a specific %).TC-15 — README developer ops
Covers:
yarn test/yarn lint, DB migrations beyonddb:up, reload webhook + authTC-16 — Contributor registration docs
Covers: how to add commands / button events / dropdown events
src/registry.tsand the interaction-create dispatchers.TC-17 — Existing docs cross-links
Covers:
docs/cards.md,docs/google-drive-sync.md,docs/logger.mdTC-18 — Smoke regression (manual)
After the above, in a test guild:
/dropor/multidrop→ claim a card./inventorypaginate;/viewa card;/seriespaginate;/sacrifice;/trade(cancel before complete);/stats;/daily.Expect: no crashes, no missing replies, images still generate on success.
Criteria were specific enough to script without going back to
needs/criteria. Moving toneeds/approval.Am happy for this to be worked on
Picked this up on the back of your "Am happy for this to be worked on" - PR #512 on
cursor/487-2026-code-clean-up, branched fromrelease/0.12.0. It is marked ready and waiting on your approval. Note the issue had nostep/*label, so I treated your comment as the go-ahead and moved it throughstep/doingtostep/review.Done: the whole Code cleanup section. All ten items. Highlights worth your eye:
awaittheir handlers, so a rejected command/button/dropdown reaches thetry/catchinstead of becoming an unhandled rejection. The error reply usesfollowUpwhen the interaction was already deferred, which is what most handlers do.POST /api/reload-dbis now authenticated. This needs an operator action: addWEBHOOK_TOKENto the deployed.env, or the endpoint returns503after this lands. It is deliberately not inrequiredConfigs, so the bot still boots without it. Details indocs/webhooks.md.RegisterChannelUpdateEvent, which was pushing its handler ontoChannelCreate. Not on the checklist, but the same copy-paste bug in the same block.splice->slicechange inSeriesHelperis defensive, not a live bug fix. Both helpers alreadycloneDeepbefore paging, sosplicewas only ever mutating a throwaway clone.Tests: 16 suites / 90 tests -> 26 / 159. Ten new suites, including the first coverage
ImageHelperhas ever had. That closes the gap I flagged during UAT on #355, where the greyscale skip could only be verified by reading the code. The three dispatcher suites are genuine regression guards: remove theawaitand the jest run crashes.Not in the PR, and I want to flag it rather than let you find it. Three checklist items are written and verified locally but did not land, because this repo is only writable through the Forgejo contents API one whole file at a time and that ran out of room in a single run:
eqeqeq. Strict equality is applied in the files the PR already touches; about 26 more files still use==/!=.docs/cards.md/docs/google-drive-sync.md/docs/logger.mdcross-links.docs/webhooks.mddid land.tests/stringDropdowns/Inventory.test.ts.Happy to do those as a follow-up PR next run if you would rather keep this one focused, or say the word and I will add them here.
One more thing I noticed but left alone: the
rulesblock ineslint.config.mjsis scoped tofiles: ["./src", "./tests"], which matches no files. Socamelcase,comma-dangle,prefer-constand the rest are not actually being enforced right now. Fixing the glob surfaces a lot of pre-existing violations, so it probably wants its own issue.yarn build,yarn lintandyarn testare all clean on the branch.@Smithy-bot Please spin off the remaining 3 tasks into their own PRs
Spun off, one PR per task, all three branched from
release/0.12.0and marked ready:tests/stringDropdowns/Inventory.test.ts. Nine cases covering every branch of the dropdown handler, including the page-number parse. Test-only, no source changes.docs/development.mdexplains registration and dispatch, and the three existing docs are cross-linked. I also fixed two README bugs I tripped over:yarn Installand acp .env.template .envfor a file that does not exist.eqeqeqis not enabled yet, because turning it on fails lint everywhere that is not yet swept, so it has to land with the final slice.Each was verified locally on
release/0.12.0:tsc --noEmit,eslint .andjestall clean, 17 suites / 99 tests with #513's suite in the tree.Two things I want in front of you rather than buried:
#515 has a real behaviour risk. Card metadata is parsed without validation, so
card.typeis declared a number but a metadata file containing"type": "1"would have matched under==and will not under===- that card would silently vanish from/stats, the drop pool and the inventory filters. I believe strict is right, but please exercise/drop,/inventoryand/statsagainst the real card folder before releasing it. #514 adds a note todocs/cards.mdasking for parse-level validation, which is the actual fix.On finishing the sweep: the honest answer is that
yarn lint:fixwitheqeqeqenabled locally would do the remaining 73 in one go and take you a couple of minutes. I can only write one whole file per API call, which is what forced #515 to be a slice. Say the word if you would still rather I grind through it in further slices.#513 and #514 are independent of #512 and of each other, so they can merge in any order.
@Smithy-bot Those two extra things for me, please create sub tickets with the details for me to pick up
Created the two sub-tickets you asked for, assigned to you, milestone
0.12.0, left at nostep/*so you can triage them:#515"type": "1"vs1risk)eqeqeq(~73 remaining across ~37 files; localyarn lint:fixis the fast path)Prefer #516 before relying on #517 / #515 against real card JSON. The inert
eslint.config.mjsfiles: ["./src", "./tests"]glob is only noted inside #517 — say if you want that as its own ticket too.Leaving #487 at
step/review; PRs #512–#515 are unchanged and still waiting on your approval.@Smithy-bot You may now test this again
QA re-test on
release/0.12.0(42260e9) — PASS (with residual checklist notes)Triggered by your 2026-09-11 comment. Against the TC scripts from the earlier comment and the checklist that landed via PRs #512–#515 / #516 / #517:
Pipeline
yarn build(tsc)yarn lint(eslint)yarn test(jest)TC scripts (automated / static)
GuildMemebrUpdate; wired in EventExecutors/client/utilthrow "in bot.ts / appLogger.tseqeqeqenabled; only remaining!=are!= null(allowed)slice, nosplicetests/helpers/ImageHelper.test.tsgreen[]RequireWebhookToken+ tests;WEBHOOK_TOKENin.env.example+docs/webhooks.mdbugs.urlishttps://docs/development.md, webhooks.md, cross-links/drop,/inventory,/series,/sacrifice,/stats, dropdown)Residual scope (not blocking this UAT move)
The original checklist’s broader command/button/helper coverage (TC-11/12/13 gaps above) was never landed in the #487 PR set. If you still want that filled, spin a follow-up story; otherwise UAT can accept the delivered cleanup + docs + the tests that did land.
Operator reminder: deployed
.envneedsWEBHOOK_TOKENorPOST /api/reload-dbreturns 503.Moving
step/testing→step/uatand assigning to you.