JSPM

  • Created
  • Published
  • Downloads 2148
  • Score
    100M100P100Q107247F
  • License MIT

A library with helpers for react-declarative app backend development

Package Exports

  • functools-kit

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 🖋️