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/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 coordination primitives: queues, mutexes, file locks, channels, semaphores, and coalescing.@studnicky/contextPer-request async context isolation using AsyncLocalStorage.@studnicky/event-busTyped multi-topic pub/sub with per-subscriber backpressure queues.@studnicky/fsmAbstract finite state machine with async effect dispatch and singleton registry.@studnicky/drilldownDeterministic multi-level grouping, faceting, and sorting over arbitrary record data.@studnicky/loggerPluggable logging with transport architecture, child loggers, and structured builders.@studnicky/pipelineGeneric typed async pipeline for sequential context transforms.@studnicky/resilienceComposable resilience primitives: retry, circuit breaker, token bucket and sliding-window rate limiters, and dead-letter queue.@studnicky/storeObservable state stores with interchangeable persistence adapters.@studnicky/schedulerReal-time and virtual scheduler primitives for deterministic testing.@studnicky/entityEntity construction primitives with strict intake compilation and cycle-safe value-graph checks.@studnicky/visible-rangePure index/offset arithmetic for computing the visible item range of a virtualized list.@studnicky/virtual-fsIn-memory synchronous filesystem primitive with an injectable clock and zero node: imports.

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.