Skip to content

v6.0.0

Choose a tag to compare

@github-actions github-actions released this 16 Jul 01:39
Immutable release. Only release title and notes can be modified.
e1db4f7

Added

  • @studnicky/eslint-config: new folder-content-shape rule enforces that interfaces/ folders hold interface declarations (runtime contracts), types/ folders hold type alias declarations (data shapes), and other folders keep data constants (regex, enums, frozen collections — not runtime functions) grouped under a constants/ folder (or fixtures/ for test/example data). Merges the former folder-declaration-shape, constants-folder-required, and entity-namespace rules. Regex literals (/pattern/flags syntax, or new 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), and known-types-outside-adapters (bans any/unknown types 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-fields gains 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: new whole-canonical-types rule bans deriving Partial<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: new type-alias-invariants rule merges the former type-alias-must-end-type, no-readonly-in-data-type, no-type-aliasing, types-derived-from-schema, and no-prefer-existing-type rules into one shared TSTypeAliasDeclaration/TSInterfaceDeclaration visitor 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 (plain Linter.Config objects), and HexagonalSuite.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-adaptersknown-types-outside-adapters, no-bind-apply-calldirect-invocation-only, no-concat-in-loopsarray-concat-outside-loops (@studnicky/v8), no-export-aliascanonical-export-names, no-freestanding-verb-nounstatic-method-verbs, no-partial-canonical-typewhole-canonical-types, no-project-internal-acronymsdescriptive-identifiers, no-spread-in-loopsarray-spread-outside-loops (@studnicky/v8), no-suppression-commentsclean-diagnostics, no-this-aliaslexical-this-only, no-trivial-shiminline-trivial-logic, no-underscore-privatehash-private-fields. Rule behavior and messageIds 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 (formerly no-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 configurable mode: '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) suppresses mustEndType's "rename it" advice and derivedFromSchema'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. The subsumedMatch message no longer recommends Pick<X, K> as a fix, since that would directly violate whole-canonical-types.

Fixed

  • Relocated 40 type/interface declarations 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 new folder-content-shape rule.
  • @studnicky/request-executor now imports ClientConfigType/RequestContextType/ResponseContextType from @studnicky/fetch/types instead of the now-stale @studnicky/fetch/interfaces subpath.
  • 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 violations static-method-verbs' (formerly no-freestanding-verb-noun) naming-heuristic previously missed.
  • Resolved all derivedFromSchema/type-alias-invariants violations 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) across batch, 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-types violations surfaced by enabling the new rule repo-wide: dropped redundant Partial<X> wrappers where X was already fully optional, and defined explicit fully-spelled-out types where a genuine subset was needed, across batch, boundary-kit, circular-buffer, eslint-config, fetch, file-lock, request-executor, retry, sample-buffer, virtual-fs, and visible-range.