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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@salespark/api-client

v1.0.9

Published

Robust TypeScript HTTP client for front-end applications, built on Axios. Provides normalized responses, retries, timeouts, cancellation, upload/download helpers, hooks, and CRUD helpers for REST APIs. Ideal for consistent and secure API integration in mo

Readme

SalesPark API Client - Generic HTTP Wrapper v1 - Documentation

@salespark/api-client

Generic HTTP client wrapper for browser-based applications (React / Next.js).


🧭 Overview

@salespark/api-client is a lightweight HTTP abstraction built on top of Axios, designed to standardize API communication across SalesPark frontend applications.

It enforces a consistent { status: boolean, data: any } (SalesParkContract) response model, never throws exceptions, and includes built‑in retry, cancellation, and upload/download helpers.

This package is part of the SalesPark Frontend Libraries and is primarily maintained for internal use in React projects.


📦 Installation

yarn add @salespark/api-client
# or
npm install @salespark/api-client

🚀 Core API — withAuth()

The withAuth() function creates a fully configured Axios wrapper that handles authorization, retries, and consistent response normalization.

Note: The export apiClient is just an alias for withAuth, provided for naming convention convenience. Both can be used for public or authenticated APIs; there is no logic difference.

📝 Example: Using apiClient for a public API

import { apiClient } from "@salespark/api-client";

const publicApi = apiClient({ baseURL: "https://jsonplaceholder.typicode.com" });

const posts = await publicApi.getMany("/posts");
if (posts.status) {
  console.log(posts.data);
}

🔧 Initialization

import { withAuth } from "@salespark/api-client";

const api = withAuth({
  baseURL: process.env.REACT_APP_API_URL,
  authHeaders: { Authorization: `Bearer ${getToken()}` },
});

⚙️ Configuration Options

| Option | Type | Description | | ---------------- | --------------------------- | --------------------------------------------- | | baseURL | string | Base URL for all requests | | authHeaders | Record<string, string> | Authorization headers (Bearer, API key, etc.) | | defaultHeaders | Record<string, string> | Headers added to all requests | | timeout | number | Timeout per request (ms) | | onAuthError | (error, instance) => void | Triggered on 401/403 responses | | onRequest | (config) => config | Request interceptor | | onResponse | (response) => void | Response interceptor | | onError | (error) => void | Generic error handler |


🧩 Available Methods

All methods return a Promise that resolves to:

{
  status: boolean;
  data: any;
}

🔹 GET Operations

| Method | Description | Example | | ------------------------- | ------------------------------------------- | ------------------------------------------------ | | getOne(path, options?) | Fetch a single resource | api.getOne("/users/1") | | getMany(path, options?) | Fetch an array of resources | api.getMany("/users", { params: { page: 1 } }) | | get(path, options?) | Auto-detects if response is single or array | api.get("/users/1") |

🔹 Write Operations

| Method | Description | Example | | ----------------------------- | ---------------- | -------------------------------------------------- | | post(path, data, options?) | Create resource | api.post("/users", { name: "John" }) | | put(path, data, options?) | Replace resource | api.put("/users/1", { name: "Jane" }) | | patch(path, data, options?) | Partial update | api.patch("/users/1", { email: "[email protected]" }) |

🔹 Delete Operations

| Method | Description | Example | | ------------------------ | -------------------- | ------------------------ | | remove(path, options?) | Delete resource | api.remove("/users/1") | | delete(path, options?) | Alias for remove() | api.delete("/users/1") |

🔹 File Operations

| Method | Description | | ---------------------------------------- | --------------------------------- | | upload(path, fileOrFormData, options?) | Upload file with progress support | | download(path, options?) | Download file as Blob |


🧠 Example Usage

// Fetch a user
const user = await api.getOne("/users/42");
if (user.status) console.log(user.data);

// Create a new user
await api.post("/users", { name: "Alice" });

// Update user
await api.patch("/users/42", { name: "Alice Smith" });

// Delete
await api.remove("/users/42");

🔄 Retry and Timeout

Retries are automatically applied for 5xx and network errors.

await api.getOne("/stats", {
  retry: {
    retries: 3,
    baseDelayMs: 500,
    maxDelayMs: 5000,
    jitter: true,
  },
  timeout: 8000,
});

⏹️ Request Cancellation

const controller = new AbortController();

const request = api.getMany("/users", { signal: controller.signal });

setTimeout(() => controller.abort(), 2000);

When aborted, the result resolves to:

{ status: false, data: { message: "Request aborted" } }

📤 File Upload

const file = (document.getElementById("file") as HTMLInputElement).files?.[0];
if (!file) return;

await api.upload("/upload", file, {
  fieldName: "document",
  onUploadProgress: (evt) => {
    console.log(`Progress: ${(evt.loaded / evt.total) * 100}%`);
  },
});

With FormData:

const fd = new FormData();
fd.append("file", file);
fd.append("meta", "invoice");

await api.upload("/files", fd);

📥 File Download

const res = await api.download("/files/report.pdf");

if (res.status) {
  const blob = res.data.blob;
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = res.data.filename || "download";
  link.click();
  URL.revokeObjectURL(url);
}

🧱 Response Model

All methods return normalized responses.

// Success
{ status: true, data: {...} }

// Error
{ status: false, data: { message, statusCode?, code? } }

TypeScript definition:

type ApiResponse<T> = { status: true; data: T } | { status: false; data: { message: string; statusCode?: number; code?: string } };

⚡ Resource Helper

resource() is a convenience wrapper around withAuth() for REST endpoints.

import { resource } from "@salespark/api-client";

const usersApi = resource("/users", {
  baseURL: process.env.REACT_APP_API_URL,
  authHeaders: { Authorization: "Bearer token" },
});

await usersApi.list();
await usersApi.get(42);
await usersApi.create({ name: "John" });
await usersApi.update(42, { name: "Jane" });
await usersApi.remove(42);

Supported methods:

| Method | Maps to | Description | | --------------------- | ---------------------- | -------------- | | list(params?) | GET /resource | Get many | | get(id) | GET /resource/:id | Get one | | create(data) | POST /resource | Create | | update(id, data) | PUT /resource/:id | Update | | patch(id, data) | PATCH /resource/:id | Partial update | | remove(id) | DELETE /resource/:id | Delete | | action(path, data?) | POST /resource/:path | Custom action |


🧪 Error Handling Patterns

const res = await api.getOne("/users/999");

if (!res.status) {
  switch (res.data.statusCode) {
    case 404:
      console.warn("Not found");
      break;
    case 500:
      console.error("Server error");
      break;
    default:
      console.error(res.data.message);
  }
}

Async/await pattern:

async function loadUser(id: string) {
  const res = await api.getOne(`/users/${id}`);
  return res.status ? res.data : null;
}

🔐 Authentication

const api = withAuth({
  authHeaders: { Authorization: `Bearer ${getToken()}` },
  onAuthError: async (err, instance) => {
    const newToken = await refreshToken();
    instance.defaults.headers.Authorization = `Bearer ${newToken}`;
    return instance.request(err.config);
  },
});

Also supports custom headers:

const apiKeyClient = withAuth({
  authHeaders: { "X-API-Key": "abc123" },
});

🧩 Interceptors

const api = withAuth({
  onRequest: (cfg) => {
    console.log("Request:", cfg.method?.toUpperCase(), cfg.url);
    return cfg;
  },
  onResponse: (res) => {
    console.log("Response:", res.status);
  },
  onError: (err) => {
    console.log("Error:", err.message);
  },
});

⚙️ Environment Variables

REACT_APP_API_URL=https://api.example.com
const api = withAuth({ baseURL: process.env.REACT_APP_API_URL });

🛠️ Support

Got stuck? Don’t panic — we’ve got you covered.

🤖 AI Assistant

We built a custom AI Assistant trained only on @salespark/api-client.
It answers implementation and troubleshooting questions in real time:

👉 Ask the API Client GPT:
https://chatgpt.com/g/g-68a9bafde1c48191b720cd55b6cd4e4a-salespark-api-client-v1

(Free to use with a ChatGPT account)


🔒 Internal Usage Notice

This package is primarily designed and maintained for internal use within the SalesPark ecosystem. While it can technically be used in other Node.js/Mongoose projects, no official support or guarantees are provided outside of SalesPark-managed projects.

All code follows the same engineering standards applied across the SalesPark platform, ensuring consistency, reliability, and long-term maintainability of our internal systems.

⚡ Note: This package is most efficient and works best when used together with other official SalesPark packages, where interoperability and optimizations are fully leveraged.

Disclaimer: This software is provided “as is”, without warranties of any kind, express or implied. SalesPark shall not be held liable for any issues, damages, or losses arising from its use outside the intended SalesPark environment.

Organization packages: https://www.npmjs.com/org/salespark


📄 License

MIT © SalesPark


Document version: 4
Last update: 01-11-2025