Skip to content

Endpoint table refactor + threadiverse/testing package#44

Open
aeharding wants to merge 5 commits into
mainfrom
refactor/endpoint-table
Open

Endpoint table refactor + threadiverse/testing package#44
aeharding wants to merge 5 commits into
mainfrom
refactor/endpoint-table

Conversation

@aeharding

Copy link
Copy Markdown
Owner

Summary

First wave of the maintainability/devex improvements:

  • Endpoint table (src/endpoints.ts): single source of truth mapping every BaseClient method to its response Zod schema, compile-checked against the declared return types. SafeClient and ThreadiverseClient are now derived from it (−526 lines of mechanical boilerplate that could silently drift). Adding an endpoint = declare on BaseClient + add a table row + implement in providers.
  • Validated discovery: wellknown.ts Zod-validates nodeinfo payloads (was a blind cast) and throws UnexpectedResponseError instead of bare Error.
  • Per-client discovery cache: ThreadiverseClientOptions.discoveryCache for SSR/tests; constructor options now optional (matches README example).
  • Table-driven conformance suite: every endpoint × every provider asserted to exist, delegate, and actually validate responses (25 → 330 tests).
  • threadiverse/testing subpath export: FakeInstance (framework-agnostic fake server: nodeinfo discovery, route table, request recording, fetch + Playwright adapters) and FakeLemmyV1Instance with wire builders type-checked against lemmy-js-client-v1. Round-trip contract test runs a real ThreadiverseClient against the fake through discovery → adapter → compat → canonical validation.

The typed builders already caught drift in Voyager's hand-written e2e fixtures: Community.description / Site.description / Post *_rank fields don't exist in v1, PrivateMessage.read is gone, enum casing ("List" vs "list"), outdated LocalSiteRateLimit shape.

Also drops the stray test-request-bug.js.

Verification

  • threadiverse: lint, typecheck, 330/330 tests, build
  • Voyager (local install): typecheck, 237/237 unit tests, 71/71 lemmyv1 e2e on chromium with its fixtures ported to threadiverse/testing (branch feat/adopt-threadiverse-testing, PR to follow after a release)

…oint table

src/endpoints.ts is now the single source of truth for the public API
surface, mapping every BaseClient method to the Zod schema that validates
its response (null = nothing to validate). The schema outputs are checked
against BaseClient return types at compile time.

SafeClient's 358 lines of hand-written parse wrappers and
ThreadiverseClient's 455 lines of hand-written delegation collapse into
loops over the table, so the three layers can no longer drift. Adding an
endpoint is now: declare on BaseClient, add a table row, implement in
providers.
…t options

- wellknown.ts now Zod-validates both nodeinfo payloads instead of blind
  casts (the last unvalidated network boundary), and throws
  UnexpectedResponseError instead of a bare Error when no 2.x link exists
- new ThreadiverseClientOptions.discoveryCache lets server-side/test
  callers scope discovery per client instead of the process-global map
- ThreadiverseClient options param is now optional, matching the README
  example
- drop stray test-request-bug.js debug script
Iterates src/endpoints.ts to assert, for every endpoint: each provider
(unsafe + safe) implements it, ThreadiverseClient delegates it, and
SafeClient actually routes its response through the declared Zod schema
(or deliberately passes through). New endpoints get conformance coverage
automatically by virtue of being added to the table.

Also makes SafeClient resolve the wrapped method at call time, matching
the dynamic dispatch the previous super.method() implementation had.
…my v1)

New ./testing subpath export so consumers stop hand-maintaining untyped
wire-format fixtures and discovery mocks in their e2e suites:

- FakeInstance: framework-agnostic fake server core — nodeinfo discovery,
  route table with per-test overrides, request recording (calls /
  waitForCall), loud 404s for unmocked routes, abort simulation — with
  adapters for fetch (vitest / fetchFunction) and Playwright (install(page))
- createLemmyV1Builders: wire-format fixture builders type-checked against
  lemmy-js-client-v1, so bumping the upstream client turns fixture drift
  into compile errors (already caught: Community.description,
  Post.*_rank fields, PrivateMessage.read, Site.description, enum casing)
- Wire<T>: allows JSON null wherever upstream types say optional, matching
  what real servers send
- FakeLemmyV1Instance: FakeInstance pre-seeded with v1 app-startup routes
- round-trip contract test: real ThreadiverseClient against the fake via
  fetchFunction, through discovery, the v1 adapter, compat, and canonical
  Zod validation
page.route() returns Promise<Disposable> in recent Playwright versions, so
the structural PageLike type now accepts any route() return.
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