v6.0.0
Immutable
release. Only release title and notes can be modified.
Added
@studnicky/eslint-config: newfolder-content-shaperule enforces thatinterfaces/folders holdinterfacedeclarations (runtime contracts),types/folders holdtypealias declarations (data shapes), and other folders keep data constants (regex, enums, frozen collections — not runtime functions) grouped under aconstants/folder (orfixtures/for test/example data). Merges the formerfolder-declaration-shape,constants-folder-required, andentity-namespacerules. Regex literals (/pattern/flagssyntax, ornew RegExp('pattern', ...)with an inlined string pattern) are zero-tolerance — a single inline regex is flagged, unlike the 2+ threshold for other constants, since a regex pattern is a data constant exactly like an enum value and must never be declared inline.@studnicky/eslint-config: new hexagonal-architecture layer-boundary rule category for consuming applications —layer-import-boundary(enforces a configurable layer allow-matrix on imports),domain-purity(forbids impure imports/calls inside a configurable domain layer),adapter-only-import(restricts concrete third-party dependencies to a configurable adapters layer), andknown-types-outside-adapters(bansany/unknowntypes everywhere outside a configurable adapters layer — adapters are the only layer permitted to hold untyped intake data; their job is converting it to known shapes).hash-private-fieldsgains an optional, layer-scoped// external-contract: <reason>directive-comment exemption for intake/hook-body fields whose underscore-prefixed names are dictated by a fixed external contract.HexagonalSuite.create(...)wires all four rules from one shared layers/sourceRoot configuration.@studnicky/eslint-config: newwhole-canonical-typesrule bans derivingPartial<X>/Pick<X, K>/Omit<X, K>from any canonical, codebase-owned named type or interface. A partial type masks the real data shape; consumers must always be aware of every property a canonical shape carries. There is no directive-comment exemption for this rule — genuinely different shapes must be defined explicitly, in full.@studnicky/eslint-config: newtype-alias-invariantsrule merges the formertype-alias-must-end-type,no-readonly-in-data-type,no-type-aliasing,types-derived-from-schema, andno-prefer-existing-typerules into one sharedTSTypeAliasDeclaration/TSInterfaceDeclarationvisitor with five independently toggleable checks. Types imported from external (node_modules) packages are automatically exempt from the schema-derivation check via real type-checker resolution, not manual directives.@studnicky/eslint-config: domain-grouped suite/preset configs —entitySuite,hygieneSuite,v8Suite(plainLinter.Configobjects), andHexagonalSuite.create(...)(a factory, since its rules share layer configuration) — for one-import consumption instead of wiring every rule individually.
Changed
@studnicky/eslint-config: every rule id previously framed as a prohibition (no-*) is renamed to a positive framing, so a rule's name states what it enforces rather than what it forbids:no-any-unknown-outside-adapters→known-types-outside-adapters,no-bind-apply-call→direct-invocation-only,no-concat-in-loops→array-concat-outside-loops(@studnicky/v8),no-export-alias→canonical-export-names,no-freestanding-verb-noun→static-method-verbs,no-partial-canonical-type→whole-canonical-types,no-project-internal-acronyms→descriptive-identifiers,no-spread-in-loops→array-spread-outside-loops(@studnicky/v8),no-suppression-comments→clean-diagnostics,no-this-alias→lexical-this-only,no-trivial-shim→inline-trivial-logic,no-underscore-private→hash-private-fields. Rule behavior andmessageIds are unchanged — only the rule id, exported symbol, and filename changed. Breaking for any consumer referencing these rule ids directly.@studnicky/eslint-config:static-method-verbs(formerlyno-freestanding-verb-noun) no longer detects violations by matching a hardcoded list of English verb-prefix names; it now uses real structural (and optionally type-aware) AST analysis via a configurablemode: 'any' | 'structural' | 'typed'option (default'structural').single-export's error-class detection now resolves the superclass through the TypeScript type checker instead of checking whether its name ends in"Error".@studnicky/eslint-config:type-alias-invariants's checks now sequence so contradictory advice on the same declaration can't fire together — a verdict that recommends deleting a declaration entirely (noAliasing's naked/primitive/generic-forwarding aliases,noPreferExisting's exact/near/subsumed duplicates of an imported type) suppressesmustEndType's "rename it" advice andderivedFromSchema's "move it into an entity" advice on that same node, since renaming or entity-ifying a declaration that should be deleted is contradictory guidance. ThesubsumedMatchmessage no longer recommendsPick<X, K>as a fix, since that would directly violatewhole-canonical-types.
Fixed
- Relocated 40
type/interfacedeclarations across 11 packages (batch,clock,errors,fetch,json,logger,retry,scheduler,throttle,timing,visible-range) to the folder matching their actual declaration form, per the newfolder-content-shaperule. @studnicky/request-executornow importsClientConfigType/RequestContextType/ResponseContextTypefrom@studnicky/fetch/typesinstead of the now-stale@studnicky/fetch/interfacessubpath.- Converted 60 freestanding module-scope functions across
@studnicky/eslint-config's own rule source,errors,retry,throttle,config,logger, and 13 demo example scripts to static class methods, closing the real violationsstatic-method-verbs' (formerlyno-freestanding-verb-noun) naming-heuristic previously missed. - Resolved all
derivedFromSchema/type-alias-invariantsviolations surfaced by enabling full enforcement repo-wide: converted inline type-literal aliases into JSON-Schema-derived entity namespaces (renamed*TypeEntity→*Entity, since the namespace itself is the entity and already contains.Type) acrossbatch,boundary-kit,circular-buffer,concurrency,config,entity-store,errors,fetch,flag-evaluator,health-registry,idempotency-guard,json,logger,mutex,resilience,retry,sample-buffer,scheduler,system,throttle,timing,virtual-fs,visible-range, and 17 smaller packages, or added honest// json-schema-uninexpressible: <reason>directives where a shape is genuinely inexpressible (function types, generics,unknown, class instances, opaque handles). - Resolved all 39
whole-canonical-typesviolations surfaced by enabling the new rule repo-wide: dropped redundantPartial<X>wrappers whereXwas already fully optional, and defined explicit fully-spelled-out types where a genuine subset was needed, acrossbatch,boundary-kit,circular-buffer,eslint-config,fetch,file-lock,request-executor,retry,sample-buffer,virtual-fs, andvisible-range.