@kawaiininja/fetch
v1.0.61
Published
Core fetch utility for Onyx Framework
Maintainers
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
HttpOnlycookies + Automatic CSRF token rotation.
- Native: Uses
- ⚡ 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
- Context Initialization:
ApiProvidercreates an immutable configuration bridge. - Platform Awareness: The library automatically switches between
Authorizationheaders (Native) andX-CSRF-Token(Web). - 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.
