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

ftched

v1.0.2

Published

Next generation zero config data engine for JS/TS with SWR and AES-GCM encryption.

Readme

ftched

A next-generation, zero-configuration data orchestration engine for JavaScript and TypeScript.

ftched handles the entire lifecycle of server-side data in a client application: fetching, intelligent caching, background revalidation, request deduplication, optimistic mutations, encrypted persistence, CSRF protection, schema validation, and React integration — with zero configuration and zero production dependencies.


Why ftched

| Capability | fetch | axios | ftched | | :----------------------------------------------- | :-----: | :-----: | :------: | | Returns data directly (no .json(), no .data) | No | Yes | Yes | | Global SWR cache | No | No | Yes | | Request deduplication | No | No | Yes | | Race condition prevention | No | No | Yes | | Automatic retry with exponential backoff | No | No | Yes | | Tag-based cache invalidation | No | No | Yes | | Optimistic mutations with rollback | No | No | Yes | | AES-GCM encrypted local persistence | No | No | Yes | | Automated CSRF token injection | No | Partial | Yes | | Sensitive header cache protection | No | No | Yes | | Schema validation (Zod / TypeBox) | No | No | Yes | | React hooks synchronized with the cache | No | No | Yes | | Zero production dependencies | Yes | No | Yes |


Installation

npm install ftched

React hooks (optional):

npm install react

Quick Start

import { ftched } from "ftched";

// GET — returns your data directly
const user = await ftched("/api/users/1");

// POST
const created = await ftched.post("/api/posts", { title: "Hello" });

// With caching, retries, and tags
const feed = await ftched("/api/feed", {
  staleTime: "1m",
  cacheTime: "24h",
  tags: ["feed"],
  retry: 3,
});

Core Methods

ftched(url, options); // GET by default
ftched.get(url, options);
ftched.post(url, body, options);
ftched.put(url, body, options);
ftched.patch(url, body, options);
ftched.delete(url, options);
ftched.stream(url, options); // Returns ReadableStream
ftched.mutate(url, variables, options); // Full mutation engine

All methods return the parsed JSON body. Pass full: true for the complete response object including status, headers, and fromCache.


Options

| Option | Type | Default | Description | | :--------------- | :----------------------- | :--------------- | :----------------------------------------------------------------------------------- | | key | string | Auto-derived | Override the cache key. | | staleTime | number \| string | 0 | Time before background revalidation. Accepts '30s', '5m', '2h', '1d', or ms. | | cacheTime | number \| string | '5m' | Time before full cache expiry. | | tags | string[] | [] | Group invalidation tags. | | retry | number | 0 | Retry attempts on failure with exponential backoff. | | retryDelay | number | 1000 | Base retry delay in ms. | | schema | Zod / TypeBox | — | Runtime response validation. | | full | boolean | false | Return FtchedResponse object instead of raw data. | | xsrfCookieName | string | 'XSRF-TOKEN' | Cookie name to read the CSRF token from. | | xsrfHeaderName | string | 'X-XSRF-TOKEN' | Header name to inject the CSRF token into. | | signal | AbortSignal | — | External cancellation signal. | | headers | Record<string, string> | — | Additional request headers. |


Caching

The SWR pattern serves cached data immediately while refreshing in the background.

const posts = await ftched("/api/posts", {
  staleTime: "30s",
  cacheTime: "10m",
  tags: ["posts"],
});

See docs/core/caching.md for keys, time formats, and tag invalidation.


Mutations

Full write lifecycle with optimistic updates and automatic rollback.

await ftched.mutate(
  "/api/posts",
  { title: "New" },
  {
    key: "posts",
    onMutate: (vars) => [{ id: 99, ...vars }],
    onError: (err, vars, rollback) => rollback(),
    onSuccess: (data) => console.log("Saved", data.id),
    invalidateTags: ["posts"],
  },
);

See docs/core/mutations.md for the complete lifecycle API.


Security

Three built-in security mechanisms — all automatic:

  • CSRF tokens injected into all write requests from browser cookies
  • Sensitive header shield prevents caching authenticated responses
  • AES-GCM encryption for localStorage persistence via EncryptedLocalStorageAdapter

See docs/security.md.


Interceptors

Globally transform requests and responses.

ftched.interceptors.useRequest(async (options) => ({
  ...options,
  headers: {
    ...options.headers,
    Authorization: `Bearer ${getToken()}`,
  },
}));

See docs/interceptors.md.


React Hooks

import { useQuery, useMutation } from 'ftched';

function Posts() {
  const { data, loading } = useQuery('/api/posts', { staleTime: '1m' });
  const { mutate } = useMutation('/api/posts', { invalidateTags: ['posts'] });

  return (
    <>
      {data?.map(p => <div key={p.id}>{p.title}</div>)}
      <button onClick={() => mutate({ title: 'New' })}>Add</button>
    </>
  );
}

See docs/react.md.


Encrypted Persistence

import { ftched, EncryptedLocalStorageAdapter } from "ftched";

const client = ftched.create({
  ...ftched.context,
  adapter: new EncryptedLocalStorageAdapter("my-32-char-secret"),
});

See docs/adapters.md.


Full Documentation

| Document | Topic | | :----------------------------------------------------------------- | :--------------------------------------------- | | docs/introduction.md | Architecture, philosophy, feature overview | | docs/getting-started.md | Installation and first steps | | docs/core/caching.md | SWR cache, keys, tags | | docs/core/mutations.md | Mutations, optimistic updates, lifecycle | | docs/core/networking.md | Retry, deduplication, abort pooling, streaming | | docs/core/schema-validation.md | Zod and TypeBox validation | | docs/security.md | CSRF, header shield, AES-GCM encryption | | docs/interceptors.md | Request and response interceptors | | docs/adapters.md | Storage adapters and custom adapter API | | docs/react.md | useQuery and useMutation hooks | | docs/instances.md | Isolated instances with ftched.create |


License

MIT