Skip to content

feat: standalone endpoints, endpoint schemas and readable call hovers (0.1.0-rc.1) - #5

Merged
monarcode merged 9 commits into
mainfrom
next/0.1.0-rc.1
Oct 30, 2026
Merged

monarcode merged 9 commits into
mainfrom
next/0.1.0-rc.1

Conversation

@monarcode

Copy link
Copy Markdown
Owner

Second release candidate for 0.1.0. It sets the version to 0.1.0-rc.1. The full notes are under ## 0.1.0-rc.1 in CHANGELOG.md.

Added

  • Endpoint schemas. Endpoints have output, error and input properties, holding the schemas they were defined with. error is the schema HttpError.body is decoded with: the endpoint's own error, then the client's defaultError, then Schema.Unknown.
  • Endpoints without a client. Fetch.endpoint(route, definition) defines an endpoint as frozen data that can be exported at module level, next to its schemas. client.bind(definition, options?) turns it into an endpoint of that client, the same one client.endpoint makes. Plugin overrides are given when binding, so they're checked against that client's plugins.
    • New types: UnboundEndpoint, UnboundDefinition, BindMethod and BindOptions.
    • The todos module in examples/app now defines its endpoints this way.

Changed

  • Call hovers show the errors. Calls and endpoints are typed as Effect.Effect<A, E, R> with the errors and services written out, rather than as CallEffect<…>. Hovering a call now shows something like Effect<{ readonly id: number }, NetworkError | DecodeError | HttpError.With<unknown>, never>. AGENTS.md rule 3 records this exception to "named types only". The type tests check that the written-out types match CallError and CallServices.

Fixed

  • Redacted query values. A Redacted value in query is sent as its value. Effect 4.1 added Redacted to UrlParams.Coercible, but effetch passed every value through String(), so it sent token=<redacted>.

Type-level changes for consumers

These don't change runtime behavior.

  • TypeScript can no longer infer CallEffect's type parameters from a call. A helper typed (call: CallEffect<O, EB, I, Ps>) should take <A, E, R>(call: Effect.Effect<A, E, R>) instead.
  • Endpoint values built by hand, such as test doubles, need output, error and input.
  • Client values built by hand need bind.

Tooling

  • Dev dependencies:
    • effect and @effect/vitest go to 4.1.0;
    • @effect/language-service goes to 0.87.5.
  • The effect peer range stays ^4.0.0.
  • The tarball smoke test covers Fetch.endpoint, client.bind and the endpoint schema properties.
  • The editor check asserts that call and endpoint hovers show the errors and services.

Verification

  • pnpm run check passes:
    • lint, format and typecheck;
    • the docs check, including 112 compiled examples;
    • 435 tests, including the type tests;
    • build, publint and attw;
    • the tarball smoke test with the editor check.
  • A consumer project on effect@4.0.0 typechecks and runs, with both NodeNext and Bundler resolution and skipLibCheck: false.

Fetch.endpoint(route, definition) returns frozen data (route, method,
path, schemas, headers) that can live at module level. client.bind
turns it into the same Endpoint client.endpoint makes. Plugin overrides
are given when binding; a definition without `error` uses the client's
defaultError.

Adds UnboundEndpoint, UnboundEndpointDefinition, BindMethod and
BindOptions. The example app's todos module now defines its endpoints
in contract/ and binds them in data/.
…finition`

- rename the exported type in `Endpoint.ts` and the `index.ts` export list
- update the README API list and the changelog entry to match
The oldest-supported-effect CI job typechecks with effect 4.0.0, where
UrlParams values are strings. Cast the whole conditional in toParam so it
compiles with both versions, and run the Redacted query tests only when the
installed Effect sends Redacted values as their value.
@monarcode
monarcode merged commit 00d6e69 into main Oct 30, 2026
2 checks passed
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