Skip to content

Repository files navigation

@studnicky/substrate: subclass-first TypeScript primitives — retry, throttle, mutex, scheduler, clock, pipeline, and more, each a usable class and an extension base

@studnicky/substrate

Subclass-first TypeScript primitives.

CI docs node release

Documentation · Releases

A subclass-first toolkit of TypeScript primitives — retry, throttle, mutex, scheduler, clock, context, pipeline, logger, errors, json, and more. Stateful primitives use explicit factories, direct operations, protected lifecycle hooks, and named state transitions; stateless utilities expose focused static operations.

Architecture

  • Subclass-first: Every public API delegates to documented protected seams. Some seams are passive observer hooks; some are in-band behavioral hooks that transform, classify, or intercept the operation itself.
  • One public path: Import package-owned symbols from @studnicky/<package>, construct stateful primitives through Class.create(config), and invoke their direct operation methods. These root imports and direct factories define the public API.
  • Dependency ownership: Composition packages expose their own behavior and contracts without proxy-exporting dependency functionality. Consumers import dependency-owned values and types from the dependency root.
  • No observability in bare classes: Telemetry seams are protected no-op hooks (onRetry, onThrottle, onAcquire, etc.). Consumers add metrics and logging by overriding those hooks; the base implementation has zero dependency on any logger or metrics backend. Observer hooks stay observational. Behavioral hooks remain in-band and are documented per package.
  • No exported stateful singletons: Stateless utilities are pure-static classes; stateful classes are created explicitly and injected. Stateful transition systems use named funnels and protected lifecycle hooks.

Packages

Package Description
@studnicky/batch Batch concurrent execution for processing items in controlled batches
@studnicky/boundary-kit Boundary Kit — composes @studnicky/throttle, /resilience, and /retry into a fixed-order boundary call pattern
@studnicky/bounded-dispatcher Bounded work dispatch pattern composing @studnicky/concurrency's Semaphore, /event-bus, and /scheduler
@studnicky/cache LRU cache with optional TTL and capacity bounds
@studnicky/circular-buffer Generic circular buffer with O(1) push and shift operations
@studnicky/clock Wall-clock and monotonic time primitives with injectable providers for deterministic testing
@studnicky/concurrency Keyed async channels, semaphore, and coalesce primitives
@studnicky/config Configuration validation and clamping utilities
@studnicky/context Per-request async context isolation using AsyncLocalStorage
@studnicky/entity-store Normalized, ID-indexed entity collection with CRUD operations and O(1) lookup
@studnicky/errors Standardized error handling for all modules
@studnicky/eslint-config Shared ESLint flat config for @studnicky packages
@studnicky/event-bus Publish/subscribe event bus with backpressure-aware queues
@studnicky/fetch Professional HTTP client with timeout, interceptors, and configured clients for Node.js
@studnicky/file-lock Process-level advisory file locking
@studnicky/flag-evaluator Local deterministic feature-flag evaluation with percentage rollout and observability hooks
@studnicky/fsm Abstract finite state machine base class with effect interpreter
@studnicky/health-registry Named async health-check registry with worst-status-wins aggregation
@studnicky/idempotency-guard Idempotency key guard composing cache, concurrency, and json: dedupes concurrent calls, replays cached results within a TTL window, rejects key reuse with a different payload
@studnicky/json JSON/object value-tools: deep merge, clone, equal, freeze, path access, sort, patch, hash
@studnicky/keyed-rate-limiter Per-key rate limiting composing cache and resilience: lazily creates one rate-limiting strategy per key, evicting idle keys via LRU+TTL
@studnicky/keyed-work-gate Keyed single-flight and serialized work gate composing @studnicky/mutex and @studnicky/concurrency's Coalesce
@studnicky/logger Pluggable logging interface with Pino wrapper, child loggers, and metadata support for Node.js
@studnicky/memoize Pure function memoization composing cache and concurrency: LRU+TTL result caching keyed by a caller-supplied key derivation, with in-flight call dedup
@studnicky/mutex Key-based async mutex for preventing race conditions in concurrent operations
@studnicky/paginator Cursor/page-list state tracker for paginated data sources
@studnicky/pipeline Generic typed async pipeline for sequential context transforms
@studnicky/predicates Type-safe predicates and coercion utilities
@studnicky/process-kit Reducer-with-effects process pattern composing @studnicky/fsm and /scheduler
@studnicky/request-executor One-shot request execution pattern composing @studnicky/fetch, /retry, /signal, /timing, and /context
@studnicky/resilience Circuit breaker, token bucket, and dead-letter queue primitives
@studnicky/retry Generic async retry utility with extensible error classification
@studnicky/sample-buffer Fixed-capacity circular buffer for numeric samples with percentile calculation
@studnicky/scheduler Scheduler primitives — real-time (setTimeout/setInterval) and virtual (min-heap, deterministic) implementations
@studnicky/signal Instance-based AbortSignal composition and timeout utilities
@studnicky/sliding-window-limiter Sliding-window rate limiter: exact timestamp-log or approximate blended-counter algorithm
@studnicky/system CPU/GPU/memory/platform detection for worker sizing
@studnicky/throttle Generic async operation throttle with sliding window concurrency control
@studnicky/timing High-resolution timing tracker for collecting operation metrics
@studnicky/types Shared zero-runtime utility types and type-guard helpers for @studnicky/substrate
@studnicky/visible-range Pure index/offset arithmetic for computing the visible item range of a virtualized list
@studnicky/worker-pool Bounded node:worker_threads pool that fans work items across workers with a typed message envelope and per-task timeout

Requirements

Node 24+.

Install

Packages publish to GitHub Packages. Add the registry to .npmrc:

@studnicky:registry=https://npm.pkg.github.com

Then install any package:

pnpm add @studnicky/retry

Develop

git clone https://github.com/Studnicky/substrate.git
cd substrate
pnpm install
pnpm build
pnpm run test:all
pnpm lint
pnpm docs:dev

License

MIT — see LICENSE.

Releases

Packages

Used by

Contributors

Languages