feat(effect): add getToken client option and schema-typed events - #5809
Abhikansh3 wants to merge 1 commit into
Conversation
| ```ts src/actors/counter/api.ts @nocheck | ||
| import { Action, Actor, Event } from "@rivetkit/effect"; | ||
| import { Schema } from "effect"; | ||
|
|
There was a problem hiding this comment.
🟠 Medium · Move the TypeScript example into a checked snippet
This inline TypeScript block bypasses the docs bundle's required CodeSnippet type-checking, and @nocheck additionally hides API drift. The repository's docs/CLAUDE.md explicitly forbids inline TypeScript examples for this reason. Move the complete example (including imports and actor registration) under examples/ and embed it with <CodeSnippet>; use regions if only this section should render.
There was a problem hiding this comment.
This page's five other examples (api.ts, live.ts, main.ts, client.ts) already use inline @nocheck TypeScript blocks on main, predating this PR. The new Typed Events section follows that same existing pattern for consistency with the rest of the page. Converting the whole quickstart to examples/-backed <CodeSnippet>s would be a good cleanup but is a larger, unrelated change touching content outside this PR's scope (getToken + typed events). Happy to file that as a follow-up if maintainers want it done.
Description
Addresses part of #5806, which asks for first-class, Schema-typed support for the connection/events lifecycle in
@rivetkit/effect. That issue's full scope (connections,authorize,CurrentConnection, a scoped clientconnect()with typed event streams) is a large, multi-PR effort with genuine open design questions inherited from the original SDK design (issue #4703). This PR ships the two independently well-scoped, low-risk pieces first:Client.Options.getTokenpassthrough.Client.Optionswas aPickof rivetkit'sClientConfigInputthat excludedgetToken, so there was no way to supply a short-lived, scoped token that's fetched (and refreshed on reconnect) on demand instead of a single static token.Client.makealready forwarded the wholeoptionsobject to the underlyingcreateClient(options)unchanged, so this was a type-only gap:getTokenreached the wire fine once the type allowed it through.Schema-typed events (broadcast only). Adds
Event.make(mirrorsAction.make's pattern: a value-level definition with aneffect/Schemapayload) and aneventsoption onActor.make.Actor.toLayer's wake options now includeevents: EventBroadcaster<Events>, whosebroadcast(tag, payload)encodes the payload through the declared event's schema before calling RivetKit's rawbroadcast, mirroring howActionDispatcheralready encodes/decodes action payloads. RivetKit's own event schema validation is bypassed the same way action validation already is (a bareRivetkit.event()token registers the event name without RivetKit re-validating it), so@rivetkit/effectis the single source of truth for the schema.Typed client-side subscription (
connect(...).events.<Tag>: Stream<...>) is explicitly not included here — receiving events is naturally part of the connections/client work, and building a new client-side Stream-from-callback bridge without the rest of that design in place isn't worth the risk. Today, a client subscribes to a broadcast event the same way it would for any RivetKit actor, through the raw connection's.on("EventName", ...).Type of change
How Has This Been Tested?
pnpm exec vitest --typecheck runinrivetkit-typescript/packages/effect: 146/146 tests pass across all 10 test files, zero type errors, including:Client.test-d.ts(new): type-level proofClient.Optionsnow accepts agetTokencallback.test/e2e.test.ts(new test + fixture): a newBroadcasteractor with aChimeevent, exercised end-to-end against a realrivet-engine— a raw client connects, subscribes via.on("Chime", ...), and asserts the received payload is the event's JSON-codec encoding (proving the payload went through schema encoding, not a raw pass-through).Actor.test.ts,Actor.test-d.ts,Registry.test.ts, etc.) re-verified green after the change to confirm no regressions to existing actor/action/state/client behavior.docs/actors/content/docs/quickstart/effect.mdx's feature-support table and added a "Typed Events" section with a runnable-shaped example.Checklist:
Follow-up (not in this PR)
The remainder of #5806 — connection params/state schemas, an
authorizehook with typed refusal errors,CurrentConnectionin action handlers, and a scoped clientconnect()with typed event streams — is a larger, coupled effort with open design questions (e.g. how an Effect-typedauthorizerefusal should interact with RivetKit's synchronouscreateConnStatetimeout model). Left for a follow-up PR/design discussion rather than bundled here.