Files
punktfunk/sdk/examples/couch-preset.effect.ts
T
enricobuehler f012ebbcba feat(sdk): Effect v4 + @effect/openapi-generator; typed pf.api & example ladder
Drop Orval for the first-party @effect/openapi-generator (OpenAPI 3.1 ->
Effect Schema + a typed HttpClient client) and bump effect 3.19 ->
4.0.0-beta.98. Port the hand-written surfaces to the v4 API (Result over
Either, Context.Service, Codec, Literals/Union arrays, Stream/Schedule/
Effect renames). Transport (CA-pinning fetch) and the reconnecting SSE
source are kept intact.

Make the SDK approachable for non-Effect users:
- Add pf.api.* on the Promise facade: the generated client surfaced as
  typed, Promise-native methods (await pf.api.listPairedClients()), so REST
  calls are autocompleted and checked instead of stringly-typed
  pf.request(method, path, body) + `as` casts. Zero-drift veneer over
  make(httpClient), backed by the same pinning fetch. pf.request stays as
  the untyped escape hatch.
- Re-tier examples into a 1-4 complexity ladder, rewritten onto pf.api.*
  (the typed payloads caught a wrong `launch` shape in provider-sync);
  the Effect example is labelled advanced. Add examples/ to tsconfig so
  they are typechecked (stops rot).

typecheck + 19 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 12:40:04 +02:00

30 lines
1.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ── Example 4/4 · ADVANCED, Effect-native ───────────────────────────────────────────────────
// You do NOT need this to use the SDK — examples 13 (the plain Promise `connect()` facade) cover
// most automation. Reach for `@punktfunk/host/effect` only when you're composing Effect programs
// and want the event stream, typed errors, and structured interruption as first-class values.
//
// Here: when the living-room TV starts a stream, apply a display preset — as a single composed,
// typed, interruptible program (a `Stream` of events piped into a request, provided a live layer).
import { Cause, Effect, Stream } from "effect";
import { events, PunktfunkHost, PunktfunkHostLive } from "../src/effect.js";
const program = Effect.gen(function* () {
const pf = yield* PunktfunkHost;
yield* events().pipe(
Stream.filter(
(e) => e.kind === "stream.started" && e.stream.client === "Living Room TV",
),
Stream.runForEach(() =>
pf
.request("PUT", "/display/settings", { mode: "preset", preset: "couch" })
.pipe(
Effect.catchCause((cause) =>
Effect.logWarning(`preset failed: ${Cause.pretty(cause)}`),
),
),
),
);
});
Effect.runPromise(program.pipe(Effect.provide(PunktfunkHostLive()))).catch(console.error);