Skip to content

SubstrateComposable TypeScript primitives.

Focused contracts and operations for matching, routing, filtering, state, concurrency, time, I/O, and structured errors. Consumers compose the tools into their own applications.

Substrate

Stateful primitives

@studnicky/batchBatch concurrent execution for processing items in controlled parallel groups.@studnicky/boundary-kitComposes throttle, resilience, and retry into a fixed-order boundary call pattern.@studnicky/bounded-dispatcherComposes concurrency's Semaphore, event-bus, and scheduler into a bounded work dispatch pattern.@studnicky/cacheIn-process LRU cache with optional TTL and capacity eviction.@studnicky/circular-bufferGeneric ring buffer with O(1) push and shift operations.@studnicky/clockWall-clock and monotonic time with injectable providers for deterministic testing.@studnicky/concurrencyAsync concurrency primitives: channels, semaphores, coalescing, and iterable utilities.@studnicky/contextPer-request async context isolation using AsyncLocalStorage.@studnicky/entity-storeNormalized, ID-indexed entity collection with CRUD operations and O(1) lookup.@studnicky/event-busTyped multi-topic pub/sub with per-subscriber backpressure queues.@studnicky/file-lockProcess-level advisory file locking for CLI tools and daemons.@studnicky/flag-evaluatorLocal deterministic feature-flag evaluation with percentage rollout and observability hooks.@studnicky/fsmAbstract finite state machine with async effect dispatch and singleton registry.@studnicky/health-registryNamed async health-check registry with worst-status-wins aggregation.@studnicky/idempotency-guardIdempotency key guard that dedupes concurrent calls, replays cached results within a TTL window, and rejects key reuse with a different payload.@studnicky/keyed-rate-limiterPer-key rate limiting that lazily creates one rate-limiting strategy per key, evicting idle keys via LRU+TTL.@studnicky/keyed-work-gateKeyed single-flight and serialized work gate composing mutex and concurrency's Coalesce.@studnicky/loggerPluggable logging with transport architecture, child loggers, and structured builders.@studnicky/memoizePure function memoization with LRU+TTL result caching keyed by a caller-supplied key derivation, and in-flight call dedup.@studnicky/mutexKey-based async mutual exclusion with queue and timeout support.@studnicky/paginatorCursor/page-list state tracker for paginated data sources.@studnicky/pipelineGeneric typed async pipeline for sequential context transforms.@studnicky/process-kitReducer-with-effects process pattern composing fsm, scheduler, and signal.@studnicky/request-executorOne-shot request execution pattern composing fetch, retry, signal, timing, and context.@studnicky/resilienceComposable resilience primitives: circuit breaker, token bucket, and dead-letter queue.@studnicky/retryGeneric async retry with extensible error classification and backoff strategies.@studnicky/sample-bufferFixed-capacity numeric sample buffer with percentile calculation.@studnicky/schedulerReal-time and virtual scheduler primitives for deterministic testing.@studnicky/sliding-window-limiterSliding-window rate limiter using an exact timestamp-log or approximate blended-counter algorithm.@studnicky/throttleSliding-window concurrency throttle with adaptive limits and abort support.@studnicky/timingHigh-resolution operation timing tracker using process.hrtime.bigint().@studnicky/visible-rangePure index/offset arithmetic for computing the visible item range of a virtualized list.@studnicky/worker-poolBounded worker_threads pool that fans work items across workers with a typed message envelope and per-task timeout.

Stateless utilities

ESLint Plugins

Configuration rules

@studnicky/all-types-are-entitiesDisallows free-standing type aliases outside entity namespaces.@studnicky/constants-folder-requiredRequires files with more than one top-level const declaration to live under a constants/ folder.@studnicky/entity-namespaceEntity files must export a namespace with Schema as const, type Type derived via FromSchema, and a validate type guard.@studnicky/interface-must-be-contractInterfaces express runtime contracts. Pure data shapes — every member JSON-serializable — must be schema-derived type aliases.@studnicky/interface-suffixRequires every interface declaration's name to end with 'Interface'.@studnicky/interfaces-compose-named-typesDisallows inline object-literal types inside interface bodies.@studnicky/no-bind-apply-callDisallows .bind(), .call(), and .apply() on callable receivers.@studnicky/no-export-aliasDisallows aliased exports and any non-index re-export path.@studnicky/no-freestanding-verb-nounDisallows freestanding verbNoun functions at module scope.@studnicky/no-prefer-existing-typeDisallows locally declared object types that duplicate or are subsumed by an imported type.@studnicky/no-project-internal-acronymsDisallows internal shorthand identifiers (cb, dlq, cfg, opts, ctx, idx, etc.) in favour of descriptive names.@studnicky/no-readonly-in-data-typeForbids readonly modifiers baked into exported type alias data definitions. Detection is type-checker driven; consumers declare immutability at the use site.@studnicky/no-suppression-commentsDisallows all lint and type suppression comments.@studnicky/no-this-aliasDisallows assigning this to a variable or binding it via assignment.@studnicky/no-trivial-shimDisallows wrapper functions that only forward or delegate a value without adding logic.@studnicky/no-type-aliasingDisallows naked type re-aliases, generic forwarding shims, and import aliases that hide canonical names.@studnicky/no-underscore-privateDisallows underscore-prefixed class members; use real #private fields/methods instead.@studnicky/prefer-collection-typesPrefers Set/Map over arrays and POJOs for membership tests and keyed lookups.@studnicky/require-options-objectRequires functions with two or more optional parameters to collect them into a trailing options object.@studnicky/single-exportRequires each non-index file to export exactly one named symbol matching the filename, except for exempt directories and constrained enum files.@studnicky/type-alias-must-end-typeRequires exported type aliases to end in Type.@studnicky/types-derived-from-schemaDisallows inline object-literal type aliases; requires data shapes to be derived from JSON Schema.

V8 performance rules

@studnicky/v8/arguments-objectDisallows the arguments object in functions.@studnicky/v8/array-from-iteratorsDisallows Array.from on non-array iterators in hot paths.@studnicky/v8/array-from-map-callbackDisallows the two-argument Array.from(iterable, mapFn) form.@studnicky/v8/computed-class-propertiesDisallows computed property keys in class bodies.@studnicky/v8/computed-object-propertiesDisallows computed property keys in object literals.@studnicky/v8/conditional-property-assignmentDisallows conditional this-property assignment inside a constructor.@studnicky/v8/define-propertyDisallows Object.defineProperty.@studnicky/v8/delete-propertyDisallows the delete operator on object properties.@studnicky/v8/dynamic-property-accessDisallows computed member access inside an object literal.@studnicky/v8/eval-functionDisallows eval().@studnicky/v8/for-in-loopsDisallows for...in loops.@studnicky/v8/for-of-arraysDisallows for...of over arrays; prefer index loops.@studnicky/v8/inline-arrow-functionsDisallows inline multi-statement arrow functions in a dispatch map rebuilt on every call.@studnicky/v8/inline-functionsDisallows inline function expressions in a dispatch map rebuilt on every call.@studnicky/v8/max-switch-casesRequires a dispatch map once a switch statement reaches 20 non-default cases.@studnicky/v8/memoize-array-lengthDisallows re-reading array.length in a for-loop test on every iteration.@studnicky/v8/no-concat-in-loopsDisallows Array.concat inside for loops.@studnicky/v8/no-spread-in-loopsDisallows array spread assignments inside for loops.@studnicky/v8/object-spreadDisallows object spread inside a constructor.@studnicky/v8/prototype-modificationDisallows assigning to .prototype after class definition.@studnicky/v8/regexp-in-loopsDisallows RegExp construction inside loop bodies.@studnicky/v8/switch-statementsDisallows block statement bodies in switch cases.@studnicky/v8/try-catch-in-loopsDisallows try-catch blocks inside loop bodies.@studnicky/v8/with-statementDisallows with statements.

Substrate is built around three principles that keep its tools focused, composable, and extensible:

Focused ownership. Each package owns one behavior and its contracts. A composition package owns its ordering, failure, or aggregation behavior without proxying dependency APIs or imposing application policy.

Explicit composition. Consumers import the primitives and contracts they need, supply their own policies and collaborators, and combine deterministic filters, matching evidence, selection, delivery, state, and infrastructure according to their application.

Extension seams. Stateful primitives expose direct factories and operations. Documented protected hooks and injected dependencies allow observability and application-specific behavior without coupling bare primitives to infrastructure.