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

zlient

v3.3.4

Published

A type-safe HTTP client framework with Standard Schema support - works with Zod, Valibot, ArkType, and any validation library

Downloads

137

Readme

zlient

The Type-Safe HTTP Client for Perfectionists.

NPM Version License Downloads

Build robust, type-safe API clients with runtime validation, retry logic, and zero boilerplate. Use any Standard Schema library — Zod, Valibot, ArkType, and more.

Features

  • Standard Schema: Use Zod, Valibot, ArkType, or any compatible validator. No lock-in.
  • Functional API: Define endpoints with pure functions and automatic type inference.
  • Type-Safe: Full TypeScript support. Arguments and responses are strictly typed.
  • Runtime Validation: Validate requests, responses, query params, and path params.
  • Resilience: Built-in exponential backoff retries and timeouts.
  • Auth: Logic-safe authentication providers (Bearer, API Key, Custom).
  • Real-Time: Type-safe WebSockets and Server-Sent Events (SSE).
  • Observability: Hooks for structured logging and metrics.

Installation

npm install zlient
# or
bun add zlient

Then install your preferred validation library:

# Pick one (or more!)
npm install zod       # Zod
npm install valibot   # Valibot  
npm install arktype   # ArkType

Quick Start

1. Initialize Client

import { HttpClient } from 'zlient';

const client = new HttpClient({
  baseUrls: {
    default: 'https://api.example.com',
  },
  retry: { maxAttempts: 3, baseDelayMs: 1000 },
});

2. Define Endpoint

Use createEndpoint with your favorite schema library:

Zod

import { z } from 'zod';

const getUser = client.createEndpoint({
  method: 'GET',
  path: (params) => `/users/${params.id}`,
  pathParams: z.object({ id: z.string() }),
  response: z.object({
    id: z.string(),
    name: z.string(),
    email: z.string().email(),
  }),
});

Valibot

import * as v from 'valibot';

const getUser = client.createEndpoint({
  method: 'GET',
  path: (params) => `/users/${params.id}`,
  pathParams: v.object({ id: v.string() }),
  response: v.object({
    id: v.string(),
    name: v.string(),
    email: v.pipe(v.string(), v.email()),
  }),
});

ArkType

import { type } from 'arktype';

const getUser = client.createEndpoint({
  method: 'GET',
  path: (params) => `/users/${params.id}`,
  pathParams: type({ id: 'string' }),
  response: type({
    id: 'string',
    name: 'string',
    email: 'string.email',
  }),
});

3. Call It

TypeScript will enforce inputs and infer the response type automatically.

const user = await getUser({
  pathParams: { id: '123' },
});

// `user` is typed as { id: string; name: string; email: string }
console.log(user.name);

Advanced Usage

Retry Configuration

Zlient automatically retries failed requests with exponential backoff. Customize the retry behavior:

const client = new HttpClient({
  baseUrls: { default: 'https://api.example.com' },
  retry: {
    maxAttempts: 3,           // Total attempts (including initial request)
    baseDelayMs: 1000,        // Base delay for exponential backoff
    retryMethods: ['GET', 'POST', 'PUT'],     // Methods to retry
    retryStatusCodes: [500, 502, 503, 504],   // Status codes to retry
    respectRetryAfter: true,  // Honor Retry-After header
  },
});

Authentication

Zlient provides built-in auth providers that safely handle headers.

import { BearerTokenAuth, ApiKeyAuth } from 'zlient';

// Bearer Token (Dynamic)
client.setAuth(new BearerTokenAuth(async () => {
  return await getLatestToken(); // Auto-refresh logic supported
}));

// API Key (Header or Query)
client.setAuth(new ApiKeyAuth({ header: 'X-API-KEY', value: 'secret' }));

Multiple Status Codes

Handle different responses for different status codes.

import { z } from 'zod';

const createPost = client.createEndpoint({
  method: 'POST',
  path: '/posts',
  request: z.object({ title: z.string() }),
  response: {
    201: z.object({ id: z.string(), status: z.literal('created') }),
    400: z.object({ error: z.string(), code: z.literal('validation_error') }),
  },
});

const result = await createPost({ data: { title: 'Hello' } });
// `result` type is the union of the 201 and 400 schemas

Error Handling

Validation errors are thrown as ApiError with detailed issues:

import { ApiError } from 'zlient';

try {
  await getUser({ pathParams: { id: '123' } });
} catch (error) {
  if (error instanceof ApiError && error.validationIssues) {
    // Handle validation error
    console.log(error.validationIssues);
    // [{ message: 'Expected string, got number', path: ['id'] }]
  }
}

FormData Support

Upload files and send multipart form data seamlessly.

import { z } from 'zod';

const uploadFile = client.createEndpoint({
  method: 'POST',
  path: '/upload',
  response: z.object({ fileId: z.string(), url: z.string() }),
  advanced: {
    skipRequestValidation: true, // FormData can't be validated
  },
});

const formData = new FormData();
formData.append('file', fileBlob, 'document.pdf');

const result = await uploadFile({ data: formData });

Metrics & Logging

Integrate with any monitoring stack (Datadog, Prometheus, etc.).

import { InMemoryMetricsCollector, ConsoleLogger } from 'zlient';

const client = new HttpClient({
  baseUrls: { default: '...' },
  logger: new ConsoleLogger(),
  metrics: new InMemoryMetricsCollector(),
});

Real-Time (WebSockets & SSE)

Zlient makes real-time communication as simple as HTTP requests.

WebSockets

const chatWs = client.createWebSocket({
  path: '/chat',
  send: z.object({ text: z.string() }),
  receive: z.object({ user: z.string(), text: z.string() }),
});

const socket = chatWs();
socket.on('message', (data) => console.log(data.text));
socket.send({ text: 'Hello!' });

SSE

Zlient's SSE implementation supports custom HTTP methods, request bodies, and automatic authentication.

const stream = client.createSSE({
  path: '/events',
  response: {
    message: z.object({ type: z.literal('connected') }),
    time: z.string(),
  },
  advanced: {
    method: 'POST', // Support GET (default), POST, etc.
  }
});

const sse = await stream({
  data: { filter: 'active' }, // Support request body for POST/PUT
  headers: { 'X-Custom-ID': '123' }, // Custom headers
});

sse.on('message', (data) => console.log(data.type)); // Typed as { type: 'connected' }
sse.on('time', (data) => console.log(data)); // Typed as string

Migration from v2

v3 introduces Standard Schema support. Key changes:

- import { z } from 'zod'; // Required peer dependency
+ // Use any Standard Schema library (Zod, Valibot, ArkType)

- catch (e) { if (e instanceof ZodError) { ... } }
+ catch (e) { if (e instanceof ApiError && e.validationIssues) { ... } }

Documentation

📖 Full Documentation


License

MIT © Emirhan Gumus