Skip to content

feat(routes): check SSE and live stream client URLs with typedRoutes - #741

Merged
cpojer merged 2 commits into
voidzero-dev:mainfrom
yangshun:claude/typed-stream-urls-c3b477
Nov 7, 2026
Merged

cpojer merged 2 commits into
voidzero-dev:mainfrom
yangshun:claude/typed-stream-urls-c3b477

Conversation

@yangshun

@yangshun yangshun commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

With routing.typedRoutes on, the url argument of connectEventStream() (void/sse/client) and connectLiveStream() (void/live/client) is now checked against the app's routes, like Link, router methods and c.rewrite().

Both clients accept:

  • one of the app's route URLs, including template literals for dynamic routes and a query/hash suffix (`/api/users/${id}`),
  • an absolute http:// or https:// URL, for a stream on another origin,
  • a URL object.

They reject unknown paths, ws:///wss://, mailto:, tel:, same-page ?/# URLs and unchecked string values. A string TypeScript can't check is cast with as RouteUrl, which turns the check off for that URL.

connectEventStream('/api/logs'); // ok
connectEventStream(`/api/users/${id}`); // ok
connectEventStream('https://example.com/events'); // ok
connectEventStream(path as RouteUrl); // ok, unchecked
connectEventStream('/api/lgos'); // type error
connectLiveStream('wss://example.com/live'); // type error

With the flag off, the parameter stays string | URL.

Neither client has a base-URL option: a path always resolves against the page's origin, so route checking applies to every relative string. The accepted string type (RequestUrl in route-url.ts) stays internal rather than being exported from void/routes; Href was not reused because it also allows mailto:, tel: and same-page URLs.

Docs

  • docs/guide/sse.md, docs/guide/live.md: what typedRoutes checks for the client URL and how to cast.
  • docs/guide/type-safety.md: "Checked URL strings" list, a paragraph on stream URLs, and the "What Gets Checked" table.
  • docs/reference/config.md: routing.typedRoutes.

Tests

  • packages/void/test/integration/route-url-builder.test.ts: the typed fixture (generated and package declarations) accepts a known route, a dynamic template literal, a RouteUrl, http(s) URLs, a URL and a RouteUrl cast; it rejects an unknown path, ws:///wss://, #details and an unchecked string. Reverting the SSE client's parameter to string | URL in dist makes the four SSE @ts-expect-error lines fail.
  • packages/void/test/unit/typed-navigation.typecheck.ts: with the flag off, both parameters are exactly string | URL.

🤖 Generated with Claude Code

yangshun and others added 2 commits November 7, 2026 11:00
With `routing.typedRoutes` on, `connectEventStream()` and
`connectLiveStream()` accept one of the app's route URLs, an absolute
`http://`/`https://` URL, or a `URL` object. Unknown paths, WebSocket,
`mailto:`, `tel:`, same-page URLs and unchecked strings are type errors.
With the flag off, the parameter stays `string | URL`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rls-c3b477

# Conflicts:
#	docs/guide/type-safety.md
#	docs/reference/config.md
#	packages/void/test/integration/route-url-builder.test.ts
@cpojer
cpojer self-requested a review November 7, 2026 09:57

@cpojer cpojer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So safe now.

@cpojer
cpojer merged commit bc2ffdb into voidzero-dev:main Nov 7, 2026
18 checks passed
yangshun added a commit to yangshun/void that referenced this pull request Nov 7, 2026
The main merge kept only this branch's side of the type-safety guide, which
dropped the stream client paragraph that voidzero-dev#741 added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants