Skip to content

refactor: remove duplicated and dead code without changing behavior - #1021

Merged
vladjerca merged 18 commits into
masterfrom
refactor/nado
Oct 18, 2026
Merged

vladjerca merged 18 commits into
masterfrom
refactor/nado

Conversation

@vladjerca

Copy link
Copy Markdown
Contributor

Behavior-preserving cleanup pass: removes duplicated and dead code across the API package, the OpenAPI generator and the developer portal. 18 commits, one finding each, so any single commit can be dropped. 47 files, +437 / -752.

What changed

API package (10 commits)

  • Deleted the unused searchListResponseSchema (never imported, not reachable from the package entry).
  • Reused existing schemas instead of byte-identical copies: show history now uses the episode history schema (the ShowActivityHistoryResponse type keeps its name), hidden removals use historyRemoveResponseSchema, sync ratings use mediaMutationCountsSchema.
  • Plex toggles: the four watching/watched/rated/collected objects and the three rated-only objects are declared once and the exported names alias them.
  • One internal externalVotedRatingsResponseSchema replaces five copies of externalRatingsResponseSchema.extend({ votes }), and one internal listSummaryResponseSchema replaces four { updated_at, item_count } blocks.
  • Trending search builds its path param with the public searchTypeParamFactory, so trendingSearchTypeParamFactory is gone (jsr.md updated).
  • In 11 route files, every repeated .merge() chain (up to 15 sites each) is now one file-local, non-exported const built with the same calls in the same order.

OpenAPI generator (1 commit)

  • Dropped the setOperationId and jsonQuery options; generate.ts never passes them.

Developer portal (7 commits)

  • addManager / addAllowedUser / removeManager / removeAllowedUser collapse into addMember / removeMember over a new memberPath helper (with spec).
  • fetchAccounts + DeveloperAccountState inlined into their single caller.
  • RequestEditor uses hasMissingExpectedJsonBody instead of an inline copy, and its two visually hidden label rules share one selector.
  • DeveloperApp rebuilds the request URL through one local function, GuideReader reads contents.md from GUIDE_SOURCES instead of a second import, the create-tile lock icon is one snippet, and parseOpenApiDocument holds the content-type pick and example formatting in one place each.

How behavior was checked

  • Generated openapi.json: byte-identical to master after every API commit, and the portal's static/openapi.json is identical too.
  • Built .d.ts types (build:types): byte-identical after every commit, except two internal files where an unused z import was dropped, so z.ZodX now reads import("zod").ZodX (same type, and no other declaration imports those files). Two variants that changed public declaration text were reverted.
  • Public surface: deno doc src/index.ts lists the same 429 symbols as master, all documented. deno task publish:check succeeds.
  • OpenAPI parser: parsing static/openapi.json gives a byte-identical catalog (332 endpoints).
  • Portal build: all 38 prerendered pages match master once hashed asset names, the CSP script hash and the per-commit share card are normalised.

Gates

  • api: deno task test 16 passed; openapi:validate ok; openapi tests 7 passed; publish:check Success
  • portal: deno fmt --check ok, prettier ok, svelte-check 571 files 0 errors, vitest 71 files / 367 tests (base 70 / 364; +3 for memberPath), build ok
  • Root deno fmt --check (34 files) and deno lint fail on master too and are not in CI. Lint is unchanged with built types present; without them no-slow-types goes from 523 to 545, because exported routes now reference the hoisted file-local consts. Publishing uses the built types, so JSR is unaffected (publish:check passes).

Not verified

  • No click-through of the portal in a browser. The apps/premium screens need a signed-in account and are client-rendered, so the prerendered HTML diff does not cover the lock icon snippet or the member requests. Those rely on the specs and on reading the markup.

Flagged, deliberately NOT changed

  • LikesResponse in models/index.ts is typed from episodeResponseSchema; looks like the wrong target, but it is a public type.
  • traktApiFactory reassigns cancellationId on the first request, so every later request on that client shares it.
  • favoritedMovies/ShowsResponseSchema equal the listed-item schemas except for key order; merging would reorder OpenAPI and parsed output.
  • ratedSeasonResponseSchema.ids uses the episode ids schema.
  • Playground createDeviceTokenPoller does not return after rejecting on expiry, so one more token request fires.
  • @ts-rest/open-api is unused in projects/openapi/deno.json; removing it changes deno.lock.
  • About 157 unused --ni-* / sizing tokens in the portal's copied scale files.
  • scripts/build-types.ts keeps a second copy of the module doc from mod.js (publish tooling).
  • Enum and Hot alias files (enums/*Schema.ts, movie/showHotResponseSchema.ts) and showStatsResponseSchema: inlining would move public declarations.
  • Redaction helpers that look alike in the portal, and accountRequest status messages that overlap developerErrorMessage: security and message behavior.

generate.ts only ever passes operationMapper, so the setOperationId
duplicate check, its operationId spread and the jsonQuery content
branch never ran. The mediaExamples key is still stripped from query
parameter schemas. Regenerated openapi.json is byte-identical.
Nothing imports it: searchResultResponseSchema inlines the list field
and search/index.ts never re-exported it, so it was never reachable
from the package entry. OpenAPI and built types are byte-identical.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T22:06:02.395299Z ff158e8 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

…elper

addManager, addAllowedUser, removeManager and removeAllowedUser were
four copies of one request that differed only in the URL segment and
HTTP method. addMember and removeMember now call accountRequest with
memberPath, and changeMemberRole goes through them. Same URLs, methods
and call order; memberPath has its own spec.
showActivityHistoryResponseSchema was a byte-identical copy of
episodeActivityHistoryResponseSchema. The show history routes now use
the episode schema, and the public ShowActivityHistoryResponse type
keeps its name. OpenAPI output is byte-identical.
hiddenRemoveResponseSchema was byte-identical to the sync history
remove response and was never exported. The three hidden remove routes
now use the sync schema. OpenAPI output and route types are
byte-identical.
Four toggle schemas were the same watching/watched/rated/collected
object and three were the same rated-only object. Each shape is now
declared once and the exported names alias it. OpenAPI output and
built types are byte-identical.
The added and deleted counts in the ratings sync responses re-declared
the movies/shows/seasons/episodes object that mediaMutationCountsSchema
already provides with the same key order. OpenAPI output and built
types are byte-identical.
tmdb, imdb, letterboxd and both mal blocks each re-declared
externalRatingsResponseSchema extended with the same votes field.
They now use one internal externalVotedRatingsResponseSchema. OpenAPI
output and route types are byte-identical.
The list add/remove and sync favorites add/remove responses each
re-declared the same { updated_at, item_count } list object. They now
use one internal listSummaryResponseSchema. OpenAPI output and route
types are byte-identical.
…ramFactory

trendingSearchTypeParamFactory had the same body as
searchTypeParamFactory with the type list hardcoded. The trending
route now passes the list to searchTypeParamFactory, which infers the
same tuple. OpenAPI output and the search route types are
byte-identical.
…itor

RequestEditor re-implemented the "JSON body expected but empty" rule
inline. It now calls the existing helper, which runs the same
expression, so the rule lives in one place.
restore, setValue, setServer and setMainServer each repeated the same
buildEndpointUrl call against the current server and values. They now
call refreshRequestUrl, which reads the same state.
GuideReader imported contents.md a second time with ?raw and aliased
GUIDE_SOURCES to a local name, although the GUIDE_SOURCES glob already
holds the same raw text under "contents" (GUIDES.ts reads it the same
way).
.request-line > label and .body-editor label carried the same five
declarations. They now share one rule. No other rule in the component
targets those labels, so the cascade is unchanged.
The app-limit and locked create tiles each inlined the same lock SVG.
Both now render a lockIcon snippet with identical markup.
fetchAccounts only wrapped listAccounts().catch(() => []) in a
one-field DeveloperAccountState object that its single caller
unwrapped again. refreshAccounts now runs the same expression itself.
parseRequestBody and parseResponses repeated the "prefer a JSON
content type" lookup, and the response example and required example
repeated the same string-or-JSON formatting. Two file-local helpers
now hold each rule. Parsing static/openapi.json gives a byte-identical
catalog (332 endpoints).
… file

Route tables in shows, movies, sync, lists, calendars, comments,
scrobble and the users subroutes repeated the same .merge() chains
(and scrobble the same unions) at up to 15 routes each. Each repeated
chain is now one file-local, non-exported const built with the same
calls in the same order. OpenAPI output and built types are
byte-identical after every file.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 67d66cc1bd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@vladjerca

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: ff158e8173

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@vladjerca
vladjerca merged commit 1f70f53 into master Oct 18, 2026
5 checks passed
@vladjerca
vladjerca deleted the refactor/nado branch October 18, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant