• v4.0.0 3cf913eed7

    v4.0.0
    All checks were successful
    CI / build-and-test (push) Successful in 3m8s
    Stable

    joeyr released this 2026-08-08 22:54:17 -05:00 | 3 commits to main since this release

    Changed

    • The op.gg scrapers are gone, and with them every fallback in the data
      layer.
      Counters, tier badges and rune pages each used to consult the
      published artifact first and then scrape op.gg live for anything it could not
      answer. That second path is deleted. Every provider now reads one published
      artifact, and a question it cannot answer is reported as unanswered rather
      than filled in from somewhere else.

      The reasoning is that the two paths were never the same answer. The crawler
      fetches those op.gg pages overnight, at its own pace, under fixed filters; a
      mid-draft scrape fetched a different page at a different moment. A champ
      select could be served by both, and nothing on screen said which — so a
      defensive-ban suggestion, a tier badge, or the rune page the Import button
      wrote could depend on which source happened to answer first.

      What you will notice: on patch-drop morning the board shows no counters and
      no tier badges
      until the crawler publishes for the new patch. Those
      artifacts refuse an off-patch copy on purpose — a tier list is a claim about
      this patch's meta — and the scrape that had already rolled over is no longer
      there to cover the gap. A blank badge is visibly blank; last patch's meta
      rendered as this patch's is not.

      Caches are unaffected and are not fallbacks under this rule: every provider
      still serves its own last good copy when a fetch fails, and damage splits and
      overlay benchmarks still serve an off-patch copy, because a champion's kit
      survives a patch that did not touch it.

    Removed

    • Settings.statsSource and Settings.rateLimitPerSecond. One selected between
      op.gg adapters and the other paced their page fetches; with no scraper there
      is nothing to select and nothing to pace. Both keys are ignored if present in
      an existing settings.json and dropped the next time it is written — no
      action needed. Riot API traffic (the scouting report and the benchmark
      harvest) keeps its own rate limiter at 0.75 req/s.
    • The tier-list disk cache (tier-list-cache.json under %APPDATA%). It held
      scraped pages; the counters artifact keeps its own cache, and two files with
      independent TTLs disagreeing about which was stale is a bug waiting to happen.
      The stale file is simply left unread and can be deleted.

    Fixed

    • CountersArtifactAdapter.fetchChampionStats threw synchronously out of a
      method typed to return a promise, because Promise.resolve(lookup(req))
      evaluates the lookup first. Every caller happened to sit inside a try, so it
      never surfaced — but a failure that arrives as a throw rather than a rejection
      is a trap for the next one.
    Downloads