ESLint Plugins
@studnicky/eslint-config ships two custom ESLint plugins:
@studnicky— 22 structural and semantic rules that enforce the substrate codebase doctrine.@studnicky/v8— 27 rules for V8 optimization-sensitive code and the related constructs the codebase constrains consistently.
Register both plugins in your flat config to enable the rules.
Install
Add the GitHub Packages registry to .npmrc:
@studnicky:registry=https://npm.pkg.github.comThen install the package:
pnpm add -D @studnicky/eslint-configInstall peer dependencies:
pnpm add -D eslint@>=10 typescript-eslint@>=8 @typescript-eslint/eslint-plugin@>=8 @typescript-eslint/parser@>=8 @stylistic/eslint-plugin@>=5 eslint-plugin-import-x@>=4 eslint-plugin-perfectionist@>=5 eslint-plugin-regexp@>=3 eslint-plugin-unused-imports@>=4 typescript@>=6Public API
The package root exports plugin, v8Plugin, entitySuite, hygieneSuite, v8Suite, and HexagonalSuite. Individual rule implementations stay on their plugin objects: use plugin.rules['single-export'] or v8Plugin.rules['delete-property'] when programmatic rule access is required.
Suites are opt-in
A suite is a flat-config entry bundling one domain's rules at error. Spreading a suite is a deliberate choice to adopt that whole domain; registering plugin alone enables nothing.
| Suite | Domain |
|---|---|
entitySuite | Entity and data-shape conventions — all-types-are-entities, folder-content-shape, interface-must-be-contract, interface-suffix, interfaces-compose-named-types, no-mixed-callable-shapes, type-alias-invariants, whole-canonical-types |
hygieneSuite | General code hygiene — canonical-export-names, clean-diagnostics, descriptive-identifiers, direct-invocation-only, hash-private-fields, inline-trivial-logic, lexical-this-only, prefer-collection-types, require-options-object, single-export, static-method-verbs |
v8Suite | V8 performance rules — all 27 rules in the V8 rules table below |
HexagonalSuite | Hexagonal-architecture import boundaries — adapter-only-import, domain-purity, known-types-outside-adapters, layer-import-boundary. A factory, not a static config: call HexagonalSuite.create(...) with the shared layer config, since all four rules take distinct extra options on top of a common layers/sourceRoot shape. |
Enable individual rules instead when a domain's conventions do not apply. type-alias-invariants governs how a type alias establishes schema provenance and stands on its own; all-types-are-entities additionally requires every canonical alias to be the exported Type member of an *Entity namespace, which is a convention a consumer adopts by enabling entitySuite, not a prerequisite for the other rules.
// eslint.config.mjs — one rule, without the entity conventions
import { plugin } from '@studnicky/eslint-config';
export default [
{
plugins: { '@studnicky': plugin },
rules: { '@studnicky/type-alias-invariants': 'error' }
}
];Usage
Import plugin and v8Plugin and register them in a flat-config entry:
// eslint.config.mjs
import { plugin, v8Plugin } from '@studnicky/eslint-config';
export default [
{
plugins: { '@studnicky': plugin, '@studnicky/v8': v8Plugin },
rules: {
'@studnicky/type-alias-invariants': 'error',
'@studnicky/v8/array-spread-outside-loops': 'error'
}
}
];Combine with additional rules in the same entry:
// eslint.config.mjs
import { plugin, v8Plugin } from '@studnicky/eslint-config';
export default [
{
plugins: { '@studnicky': plugin, '@studnicky/v8': v8Plugin },
rules: {
'@studnicky/type-alias-invariants': 'error',
'@studnicky/v8/array-spread-outside-loops': 'error',
'no-console': 'warn'
}
}
];Using the plugins directly
Import the raw plugin objects for hand-rolled flat config:
// eslint.config.ts
import { plugin, v8Plugin } from '@studnicky/eslint-config';
export default [
{
plugins: {
'@studnicky': plugin,
'@studnicky/v8': v8Plugin
},
rules: {
'@studnicky/single-export': 'error',
'@studnicky/v8/delete-property': 'error'
}
}
];Configuration rules
26 rules that enforce structural, semantic, and stylistic constraints.
@studnicky/explicit-return-binding, @studnicky/intake-parse-only, and @studnicky/no-unparsed-assertion are not bundled into any suite above — the latter two share the same exemptPackages boundary-package list (parsing primitives and the compile engine every intake is built from). All three are adopted individually, alongside whichever suites a consumer chooses.
V8 rules
27 rules covering V8 optimization-sensitive allocation, object-shape, iteration, and dynamic-code patterns, alongside related source constraints where measurement does not establish a V8 cost.