Runner
entrypoints/patreon.content.ts operates on *://*.patreon.com/*. It is the only component
that calls Patreon. It does nothing until it receives a message from the service worker. Thus
the extension adds no requests when the user reads Patreon.
- All calls to
fetch()are here, withcredentials: 'include'. The calls must not move to the service worker. A context in the extension origin does not reliably send the session cookies of a different origin. - The runner normalizes the data before it replies (
lib/patreon/normalize.ts). It finds each entity inincludedbytypeandid, connects the entities to their relationships, and makes the entity graph inlib/patreon/types.ts. The service worker never sees the JSON:API data. - The runner classifies each failure.
classify()changes the HTTP result into a code that the panel can explain. HTTP 401 becomessigned-out. HTTP 429 becomesrate-limited, and the runner also sends theRetry-Afterheader. A body that is not JSON becomeschallenge. HTTP 403 becomesforbidden. HTTP 400 becomesapi-shape. - The runner gets one page at a time. Each page has 20 posts (
POSTS_PAGE_SIZE). Gopher gets the next page only when the user comes to the end of the list. Gopher never reads the full history of a creator automatically. See request limits. - The runner can use a smaller query. The full
includelist is verified against the live API. If Patreon refuses it with HTTP 400, the runner sends the query again withoutinclude. The API then sends its default includes. The service worker keeps this decision inbrowser.storage.session. Post attributes also contain media URLs, thus the smaller query still shows images, text, and embedded players. - The runner replies but does not write. It sends the normalized data in a message. It never writes the cache.
Read the data layer for the endpoints the runner calls and the shape of the answers it normalizes.