functools-kit
v1.1.1
Published
A library with helpers for react-declarative app backend development
Maintainers
Readme
🛠️ functools-kit
A lightweight TypeScript utility library for async control flow, reactive programming, and functional helpers.
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.
✨ 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 likemap,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:
pubsubwith 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-kitQuick 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 callObserver / 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 8Operator: 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 withFetchErrorfor 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/releaseLockwith 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
pubsubfor message queuing,BehaviorSubjectfor state sync. 🌐 - 🤖 AI Agent Backends: Used internally by
agent-swarm-kitfor 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 🖋️
