npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@feelai/fetch-client

v1.0.10

Published

A type-safe HTTP/WebSocket client that consumes contracts defined with `@feelai/contract`. It provides fully-inferred TypeScript types for API calls, streaming, and socket connections — no manual type annotations required.

Readme

@feelai/fetch-client

A type-safe HTTP/WebSocket client that consumes contracts defined with @feelai/contract. It provides fully-inferred TypeScript types for API calls, streaming, and socket connections — no manual type annotations required.

Features

  • Type-Safe API Calls: Input and output types are automatically inferred from your contract.
  • Input Validation: Validates request input against the contract schema at runtime using typebox before sending.
  • Streaming Support: Connect to stream endpoints over WebSocket with typed event emitters.
  • Socket Support: Real-time bidirectional communication with typed client/server events.
  • Configurable Headers & Query: Hook into request lifecycle to inject auth tokens or custom query params.
  • Large Payload Chunking: Automatically splits large WebSocket messages into 1MB chunks.

Installation

bun add @feelai/fetch-client

Usage

1. Create a Client

Pass your contract and a base URL to createClient (or instantiate FetchClient directly).

import { createClient } from "@feelai/fetch-client";
import { todoListContract } from "./todoListContract";

const client = createClient(todoListContract, "https://api.example.com");

2. Call API Endpoints

Use client.fetch() to call HTTP endpoints defined in the contract's apiMap. The method, input shape, and response type are all inferred automatically.

// No input required
const tasks = await client.fetch("getTasks");
//    ^? Task[]

// With typed input
const newTask = await client.fetch("createTask", { title: "Buy groceries" });
//    ^? Task

All requests are sent as POST with a JSON body and credentials: "include" by default.

3. Connect to a Stream

Use client.stream() to open a WebSocket connection to a stream endpoint. Returns a typed Stream object with typed event handlers.

const stream = await client.stream("generateTask", { content: "Write a summary" });

stream.on("chunk", (data) => {
  console.log("Partial:", data);
});

stream.on("end", (data) => {
  console.log("Done:", data);
});

stream.on("error", (err) => {
  console.error("Error:", err);
});

4. Connect to a Socket

Use client.socket() to open a typed bidirectional WebSocket connection for real-time communication.

const socket = await client.socket("taskUpdates");

// Listen for server events
socket.on("taskCreated", (task) => {
  console.log("New task:", task);
});

// Send client events
socket.emit("subscribe", {});

5. Inject Headers & Query Params

Customize outgoing requests by assigning to initHeaders and initStreamQuery on the client instance.

client.initHeaders = () => ({
  Authorization: `Bearer ${getToken()}`,
});

client.initStreamQuery = () => ({
  token: getToken(),
});

6. Advanced Options

The fetch() method accepts standard RequestInit options plus extras:

| Option | Type | Description | | ---------------- | ------------------------ | ------------------------------------------------ | | query | Record<string, string> | Appends query parameters to the URL. | | skipValidation | boolean | Skips runtime input validation (default: false). |

const tasks = await client.fetch("getTasks", undefined, {
  query: { page: "1" },
  skipValidation: true,
});

API Reference

createClient(contract, baseUrl)

Factory function. Returns a FetchClient instance bound to the given contract and base URL.

FetchClient<TContract>

| Member | Type | Description | | -------------------------------- | -------------------------------------- | ------------------------------------------------------------- | | initHeaders | () => Record<string, string> \| void | Called before every HTTP request to inject headers. | | initStreamQuery | () => Record<string, string> \| void | Called before every stream connection to inject query params. | | fetch(path, input?, options?) | Promise<Output> | Calls an HTTP API endpoint from the contract. | | stream(path, input?, options?) | Promise<Stream<Events>> | Opens a WebSocket stream connection. | | socket(path, query?) | Promise<SocketClient<...>> | Opens a bidirectional WebSocket socket connection. |

Related Packages