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

@kawaiininja/fetch

v1.0.61

Published

Core fetch utility for Onyx Framework

Readme

@kawaiininja/fetch

A production-grade, hybrid-native HTTP client designed for the Onyx Framework.

Rating: S-Tier Utility 🏆

This package automates enterprise-grade security, CSRF handling, and platform detection (Web vs. Native Mobile), allowing you to focus on building features rather than handling HTTP boilerplate. It is optimized for high-performance React applications with built-in caching and retry logic.

🚀 Features

  • Hybrid Intelligence: Automatically detects if running on Web or Native Mobile (Capacitor).
  • 🛡️ Session Memory Vault: High-performance token caching for native apps that avoids expensive SecureStorage calls on every request.
  • Pro Security:
    • Native: Uses SecureStoragePlugin (with localStorage fallback) for secure token management.
    • Web: Uses HttpOnly cookies + Automatic CSRF token rotation.
  • ⚡ Strict Reliability:
    • Smart Deadlines: Global and per-request timeouts to prevent UI hangs.
    • Auto-Retries: Transparently retries failed network requests before surfacing an error.
  • 📦 Caching & SWR: Built-in support for Stale-While-Revalidate, custom dedupe keys, and focus-based revalidation.
  • Type-Safe & Efficient: Optimized for both TypeScript and standard JavaScript.

🛠️ Setup Guide

1. Global Provider Configuration

Wrap your application with the ApiProvider. This sets the design system and security policy for every request.

// src/main.jsx or App.jsx
import { ApiProvider } from "@kawaiininja/fetch";

const apiConfig = {
  baseUrl: "https://api.myapp.com", // Base URL for all requests
  version: "v1", // Automatically appends /v1 to non-absolute paths
  debug: true, // Detailed console logs for security & network
  timeout: 5000, // Global fallback timeout (default 5s)
  retries: 3, // Global retry attempt count
  disableCsrf: false, // Set true for local development or non-CSRF backends
  onError: (msg, status) => {
    showToast(`${status || "Error"}: ${msg}`);
  },
};

ReactDOM.createRoot(document.getElementById("root")).render(
  <ApiProvider config={apiConfig}>
    <App />
  </ApiProvider>,
);

📖 Essential Usage

1. The Standard Hook

useFetch is designed to be the primary way you interact with your API. It handles state, mounting logic, and method injection.

import { useFetch } from "@kawaiininja/fetch";

export const UserList = () => {
  // 1. Initial configuration
  // Note: state contains { data, loading, error, status }
  const { state, isLoading, isSuccess, get } = useFetch("/users", {
    swr: true,
    revalidateOnFocus: true,
  });

  // Access data via state.data
  const users = state.data;

  if (isLoading && !users) return <Skeleton />;

  return (
    <ul>
      {users?.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
      <button onClick={() => get()}>Manual Refresh</button>
    </ul>
  );
};

2. Performing Actions (Mutations)

Don't use fetch() or axios for buttons. Use the injected methods to keep security tokens consistent.

const CommentBox = ({ postId }) => {
  const { post, isLoading } = useFetch("/comments");

  const save = async (text) => {
    // Methods return the final parsed data or undefined if failed
    const result = await post({ text, postId });
    if (result) alert("Saved!");
  };

  return (
    <button onClick={() => save("Hello!")} disabled={isLoading}>
      {isLoading ? "Saving..." : "Submit"}
    </button>
  );
};

🏗️ Advanced Guides

1. Custom Error Handling

While ApiProvider has a global onError, you can handle errors locally within a request to provide specific feedback (like inline form validation).

const { post, state } = useFetch("/update-profile");

const handleSave = async () => {
  try {
    await post(formData);
  } catch (err) {
    // err.message will contain the server error or network issue
    console.log("Local error handling:", err.message);
  }
};

2. Manual Cache Manipulation

Sometimes you want to update the UI instantly (Optimistic UI) before the server responds.

const { updateData, post } = useFetch("/settings");

const toggleOption = async (id) => {
  // 1. Update UI instantly
  updateData({ [id]: true });

  // 2. Sync with server in background
  await post({ id, value: true });
};

3. Reactive Dependencies

The hook automatically refetches if the endpoint or dedupeKey changes, making it perfect for search or filtered lists.

const { state } = useFetch(`/products?category=${selectedCategory}`);
// This will automatically fire whenever selectedCategory updates!

⚙️ Configuration API Reference

ApiProvider Config (ApiConfig)

| Property | Type | Default | Description | | :------------ | :--------- | :----------- | :---------------------------------------------------- | | baseUrl | string | Required | The root URL for all requests. | | version | string | "v1" | Appended to paths that don't start with /. | | timeout | number | 5000 | Global timeout in MS. | | retries | number | 3 | Attempts before giving up. | | disableCsrf | boolean | false | Skips CSRF token retrieval if true. | | debug | boolean | false | Enables verbose security and network logs. | | onError | function | - | Call: (msg: string, status: number \| null) => void |

useFetch Options (SSSOptions)

| Option | Type | Default | Description | | :------------------ | :-------- | :--------- | :------------------------------------- | | enabled | boolean | true | Set false to skip initial mount fetch. | | swr | boolean | false | Enable caching + background updates. | | revalidateOnFocus | boolean | false | Refetch when window is focused. | | refreshInterval | number | 0 | Polling interval in MS. | | staleTime | number | 300000 | Cache fresh for 5 minutes. | | dedupeKey | string | endpoint | Custom key for caching logic. | | timeout | number | (Global) | Per-hook timeout override. | | retries | number | (Global) | Per-hook retry override. |

Returned Surface (ApiSurface<T>)

| Property | Type | Description | | :-------------------- | :-------------- | :------------------------------------------------------- | | state | FetchState<T> | Raw reactive state: { data, loading, error, status }. | | isLoading | boolean | [Alias] for state.loading. | | isError | boolean | [Alias] - true if state.error is present. | | isSuccess | boolean | [Alias] - true if request is successful with data. | | get(options) | function | Performs a GET request. | | post(data, options) | function | Performs a POST request. | | put/patch/delete | function | Corresponding HTTP methods. | | upload(formData) | function | Multipart upload helper. | | setData(data) | function | Manually override the local state.data. | | updateData(partial) | function | Merge partial updates into state.data. |


🛡️ Security & Architecture

  1. Context Initialization: ApiProvider creates an immutable configuration bridge.
  2. Platform Awareness: The library automatically switches between Authorization headers (Native) and X-CSRF-Token (Web).
  3. Execution Pipeline:
    • Step 1: Check Cache (if SWR).
    • Step 2: Ensure CSRF (if Web and not disabled).
    • Step 3: Inject Auth Headers (Native Session Memory).
    • Step 4: Execute fetch() with recursive retry logic.
    • Step 5: Parse & Commit to state.

© 2024 KawaiiNinja. Built for High-Performance Onyx Apps.