Skip to content

Latest commit

ย 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

sovi

Tiny fetch client with a simple API.

npm version

Features

  • ๐Ÿชถ Lightweight - Zero dependencies, ~1KB gzipped
  • ๐Ÿ”— Chainable API - Fluent interface for building requests
  • ๐Ÿ“ TypeScript first - Full type safety with path parameter inference
  • ๐Ÿ”„ Immutable - Each method returns a new instance
  • ๐ŸŽฏ Simple - No complex configuration needed

Installation

npm install sovi
pnpm add sovi
yarn add sovi

Quick Start

import { sovi } from "sovi";

// Create a client
const api = sovi({ baseUrl: "https://api.example.com" });

// GET request
const users = await api.url("/users").get().json();

// POST request
const newUser = await api
  .url("/users")
  .post({ name: "Kim", email: "kim@example.com" })
  .json();

// With path parameters
const user = await api.url("/users/:id", { id: 1 }).get().json();

// With query parameters
const filtered = await api
  .url("/users")
  .query({ page: 1, limit: 10 })
  .get()
  .json();

Usage

Creating a Client

import { sovi } from "sovi";

const api = sovi({
  baseUrl: "https://api.example.com",
  headers: {
    Authorization: "Bearer token",
  },
});

HTTP Methods

// GET
api.url("/users").get();

// POST
api.url("/users").post({ name: "Kim" });

// PUT
api.url("/users/:id", { id: 1 }).put({ name: "Lee" });

// PATCH
api.url("/users/:id", { id: 1 }).patch({ name: "Park" });

// DELETE
api.url("/users/:id", { id: 1 }).delete();

Path Parameters

Path parameters are automatically inferred from the URL pattern:

// TypeScript will require { id: string | number }
api.url("/users/:id", { id: 1 }).get();

// Multiple parameters
api.url("/users/:userId/posts/:postId", { userId: 1, postId: 42 }).get();

Query Parameters

api.url("/users").query({ page: 1, limit: 10 }).get();
// GET /users?page=1&limit=10

Headers

api.url("/protected").headers({ Authorization: "Bearer new-token" }).get();

Response Handling

// JSON (with type inference)
const data = await api.url<User[]>("/users").get().json();

// Text
const text = await api.url("/text").get().text();

// Blob
const blob = await api.url("/image").get().blob();

// Raw Response
const response = await api.url("/users").get().res();

Error Handling

import { sovi, SoviError } from "sovi";

try {
  const data = await api.url("/users").get().json();
} catch (error) {
  if (error instanceof SoviError) {
    console.log(error.status); // 404
    console.log(error.statusText); // "Not Found"
    console.log(error.response); // Response object
  }
}

Direct Method Calls

When using only baseUrl, you can call HTTP methods directly:

const usersApi = sovi({ baseUrl: "https://api.example.com/users" });

// These are equivalent:
usersApi.get();
usersApi.url("").get();

// With query
usersApi.query({ page: 1 }).get();

API Reference

sovi(config?)

Creates a new Sovi client instance.

Option Type Description
baseUrl string Base URL for all requests
headers Record<string, string> Default headers

Instance Methods

Method Description
.url(path, params?) Set URL with optional path parameters
.query(params) Add query parameters
.headers(headers) Add headers
.get() Send GET request
.post(body?) Send POST request
.put(body?) Send PUT request
.patch(body?) Send PATCH request
.delete() Send DELETE request

Response Methods

Method Return Type Description
.json() Promise<T> Parse response as JSON
.text() Promise<string> Parse response as text
.blob() Promise<Blob> Parse response as Blob
.arrayBuffer() Promise<ArrayBuffer> Parse response as ArrayBuffer
.formData() Promise<FormData> Parse response as FormData
.res() Promise<Response> Get raw Response object

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages