Client
OPRA provides a typed HTTP client layer that sits between your frontend code and an OPRA-powered API. It handles request building, body serialization, response parsing, interceptor chaining, and error normalization — so your application code only deals with typed inputs and outputs.
All client methods return an HttpRequestObservable, which supports both Promise and Observable usage. You can await a single response or pipe it through RxJS operators — whichever fits your stack.
Packages
| Package | Use when |
|---|---|
@opra/client | React, Vue, Node.js, or any non-Angular environment |
@opra/angular | Angular applications — uses Angular's HttpClient as the transport |
Both packages share the same API surface. The difference is the backend: @opra/client uses the browser/Node fetch API by default, while @opra/angular delegates to Angular's HttpClient so that Angular's interceptors, HttpContext, and DI system remain fully active.
Key capabilities
Type-safe requests — Generic type parameters flow from the method call through to the resolved value. No manual casting.
const order = await client.get<Order>('orders/123').getBody();
// order is typed as Order
Promise and Observable in one — Every request is an Observable you can subscribe to, or a Promise you can await. No need to choose upfront.
// Promise
const orders = await client.get<Order[]>('orders').getBody();
// Observable — combine, cancel, pipe
userId$.pipe(switchMap(id => client.get<User>(`users/${id}`))).subscribe(...);
Pluggable backend — The transport layer is swappable. FetchBackend ships by default; AngularBackend integrates with Angular's HTTP stack; you can build your own for testing or custom environments.
Interceptors — Add auth tokens, retry logic, logging, or correlation IDs once and have them apply to every request automatically.
Structured errors — ClientError exposes the HTTP status and the structured issues array from the OPRA response body, so error handling is consistent across the application.
Quick example
import { OpraHttpClient } from '@opra/client';
const client = new OpraHttpClient('https://api.example.com');
const order = await client.get<Order>('orders/123').getBody();
const created = await client.post<Order>('orders', { item: 'book' }).getBody();