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

functools-kit

v1.1.1

Published

A library with helpers for react-declarative app backend development

Readme

🛠️ functools-kit

A lightweight TypeScript utility library for async control flow, reactive programming, and functional helpers.

Ask DeepWiki npm

Build robust, production-grade applications with functools-kit! This library provides a comprehensive set of tools for async orchestration, memoization, reactive streams, and functional programming patterns. Whether you need debounced calls, cancellable promises, pub/sub messaging, or observable data streams — it's all here with a clean, type-safe API.

📚 Full Documentation


✨ Why Choose functools-kit?

  • Async Control Flow: Rich set of async wrappers — cancelable, queued, execpool, retry, lock, singlerun, afterinit — for managing concurrent, sequential, and fault-tolerant async operations. 🔄

  • 🔁 Reactive Streams: Full observer/subject pattern with Observer, Subject, BehaviorSubject, and operators like map, filter, debounce, merge, join — build reactive pipelines with ease. 📡

  • 🧠 Smart Caching: memoize, cached, ttl, router — cache results by key, by argument change, or with time-to-live expiry. Per-key state routing prevents memory leaks. 🗂️

  • 🛡️ Error Resilience: trycatch, retry, obsolete, rate — wrap functions with structured error handling, automatic retries, rate limiting, and deprecation warnings. 🚑

  • 📦 Pub/Sub Messaging: pubsub with pluggable async queue and map adapters (PubsubArrayAdapter, PubsubMapAdapter) for building message-driven workflows with backpressure. 📨

  • 🔢 Pagination & Iteration: iterateDocuments, iterateUnion, iterateList, paginateDocuments, filterDocuments, mapDocuments — async generator-based document iteration with offset/cursor pagination support. 📄

  • 🧩 Functional Helpers: compose, match, and, or, not, first, last, join, truely, str, has — compose functions and work with arrays/strings in a functional style. 🧮


🚀 Getting Started

Installation

npm install functools-kit

Quick Examples

Debounce & Throttle

import { debounce, throttle } from "functools-kit";

const onResize = debounce(() => recalcLayout(), 300);
const onScroll = throttle(() => updateHeader(), 100);

Memoize with TTL

import { ttl } from "functools-kit";

const getUser = ttl(
  async (userId: string) => fetchUser(userId),
  { key: ([id]) => id, timeout: 60_000 }
);

Cancelable Promises

import { cancelable, CANCELED_PROMISE_SYMBOL } from "functools-kit";

const fetchData = cancelable(async (url: string) => {
  const res = await fetch(url);
  return res.json();
});

const result = await fetchData("/api/data");
if (result === CANCELED_PROMISE_SYMBOL) return;

fetchData.cancel(); // cancel any in-flight call

Observer / Reactive Stream

import { Subject } from "functools-kit";

const subject = new Subject<number>();

subject
  .filter(n => n % 2 === 0)
  .map(n => n * 2)
  .debounce(200)
  .connect(value => console.log(value));

subject.next(1);
subject.next(2); // logs 4
subject.next(4); // logs 8

Operator: take, skip, distinct, group

import { Source, Operator } from "functools-kit";

Source.fromArray([1, 2, 3, 2, 1, 4, 5])
  .operator(Operator.distinct())        // remove duplicates: 1,2,3,4,5
  .operator(Operator.skip(1))           // skip first: 2,3,4,5
  .operator(Operator.take(3))           // take first 3: 2,3,4
  .connect(value => console.log(value));

Source.fromInterval(100)
  .operator(Operator.group(3))          // emit batches of 3: [0,1,2], [3,4,5]...
  .connect(batch => console.log(batch));

Execution Pool

import { execpool } from "functools-kit";

const processFile = execpool(
  async (path: string) => heavyProcessing(path),
  { maxExec: 4, delay: 50 }
);

await Promise.all(files.map(f => processFile(f)));

Lock: mutual exclusion for async code

import { Lock } from "functools-kit";

const lock = new Lock();

async function criticalSection() {
  await lock.acquireLock();
  try {
    // only one caller runs here at a time
    await writeToDatabase();
  } finally {
    await lock.releaseLock();
  }
}

// concurrent calls are serialized automatically
await Promise.all([criticalSection(), criticalSection(), criticalSection()]);

Per-Key Router Cache

import { router } from "functools-kit";

const loadCamera = router<(cameraId: number, cacheKey: string) => Promise<void>, number>(
  ([cameraId]) => cameraId,
  ([, a], [, b]) => a !== b,
  async (cameraId, cacheKey) => { await processCamera(cameraId); }
);

🌟 Key Features

  • ⚙️ singleshot / singlerun: Execute a function exactly once; reset with .clear(). 🔒
  • 🔂 queued / lock: Serialize async calls — queue or mutex-style. 🚦
  • 🕐 singletick: Coalesce multiple synchronous calls into one per event loop tick. ⏱️
  • 📡 pubsub: Message queue with lifecycle hooks (onBegin, onProcess, onEnd, onDestroy). 📬
  • 🏗️ Source: Factory for observers — createHot, createCold, fromPromise, fromInterval, fromSubject, pipe, merge, join. 🔧
  • 🎛️ Operator: Stream operators — take, skip, distinct, group, pair, strideTricks, liveness, count. 🎚️
  • 🌐 fetchApi: Typed fetch wrapper with FetchError for structured HTTP error handling. 🌍
  • 📐 ToolRegistry: Generic type-safe registry for runtime tool/plugin registration. 🗃️
  • 📊 SortedArray / LimitedSet / LimitedMap: Specialized data structures with size and score constraints. 📦
  • 🔐 Lock: Class-based mutual exclusion primitive — acquireLock / releaseLock with mis-matched release detection. 🧱

📖 API Reference

Async HOFs

| Function | Description | |---|---| | cancelable | Wraps a promise with cancellation support | | queued | Serializes calls into a promise queue | | execpool | Limits concurrent async executions | | retry | Retries on failure with configurable count/delay | | lock | Mutex for async functions | | singlerun | Runs only once until cleared | | afterinit | Skips calls until first run completes | | schedule | Defers execution with a scheduler callback | | obsolete | Marks a function as deprecated | | timeout | Wraps with a timeout, returns TIMEOUT_SYMBOL on expiry |

Caching

| Function | Description | |---|---| | memoize | Cache by key function | | cached | Cache by argument change detection | | ttl | Time-to-live cache with optional GC | | router | Per-key cached memoization | | rate | Rate limiting by key |

Reactive

| Class / Function | Description | |---|---| | Observer | Full observable implementation | | Subject | Observable + subscriber | | BehaviorSubject | Subject with current value | | Source | Observer factory methods | | Operator | Stream transformation operators | | waitForNext | Await a subject value matching a condition |

Utilities

| Function | Description | |---|---| | debounce / throttle | Rate-limit function calls | | singletick | One execution per event loop tick | | compose | Right-to-left function composition | | trycatch | Try-catch wrapper with fallback | | sleep | Promise-based delay | | createAwaiter | Create a promise with external resolve/reject | | deepFlat | Deep-flatten nested arrays | | singleshot | Run once with memoized result |

Data Structures

| Class | Description | |---|---| | Lock | Class-based mutex: acquireLock / releaseLock, throws on extra release | | SortedArray | Array sorted by numeric score with push, pop, take | | LimitedSet | Set capped at a max size | | LimitedMap | Map capped at a max size | | ToolRegistry | Type-safe runtime registry with register / get |

String & Array

| Function | Description | |---|---| | str | Join strings with separators (space, comma, newline, etc.) | | join | Merge arrays, dedup and strip nulls | | split | Split string arrays | | truely | Filter nulls from array | | first / last | Safe first/last element | | has | Membership check for Array/Set/Map | | formatText | Format string by template mask | | compareFulltext | Fulltext match against object fields | | typo | Typography constants (nbsp, emdash, etc.) |


🎯 Use Cases

  • ⚙️ Backend Services: Rate-limit external API calls, pool database queries, cache expensive computations. 🖥️
  • 📡 Event-Driven Systems: Build reactive pipelines with subjects and observers instead of raw event emitters. 🔁
  • 📄 Data Pipelines: Iterate millions of documents via async generators with filtering, mapping, and pagination. 📊
  • 💬 Real-Time Apps: Use pubsub for message queuing, BehaviorSubject for state sync. 🌐
  • 🤖 AI Agent Backends: Used internally by agent-swarm-kit for TTL caching, randomString, str utilities, and observable coordination. 🧠

🌍 Ecosystem

functools-kit is used as a core dependency in:

  • backtest-kit — TypeScript framework for backtesting trading strategies with clean architecture and real-time execution capabilities.
  • agent-swarm-kit — Multi-agent AI orchestration framework
  • react-declarative — Declarative React application framework

🤝 Contribute

Fork the repo, submit a PR, or open an issue on GitHub. 🙌

📜 License

MIT © tripolskypetr 🖋️