Skip to content

v1.4.0

Choose a tag to compare

@stevensacks stevensacks released this 04 Jun 15:54
· 59 commits to main since this release
7a3f355

Minor Changes

  • #22 67be5dd Thanks @stevensacks! - Enable architecture-boundary enforcement. Turn on
    import-x/no-restricted-paths at error in the guardrails layer, scoped to
    the app non-test/story file set (${sourceDir}/**/!(*.test|*.stories).ts?(x)).
    No new dependency: eslint-plugin-import-x (v4.16.2) is already wired in, and
    airbnb-extended ships this rule off, which guardrails (spread after base)
    now overrides.

    It encodes GAIA's canonical app/ layout and its import-direction invariant.
    Imports may only flow from a higher layer to a lower one; types/ is a pure
    leaf importable by everyone:

    routes -> pages -> components -> { hooks, state } -> services -> utils -> types
    

    One zone per lower layer names the higher layers it must not import (collapsed
    with from arrays, supported in 4.16.2). Because routes is in every from
    set, nothing may import a route. middleware, sessions.server, assets,
    languages, and styles are intentionally left unconstrained.

    Zone target/from paths resolve against process.cwd() (the consuming
    project's root where eslint runs), not this package's location in
    node_modules, so ./${sourceDir}/... correctly points at the consumer's source
    tree. No basePath override is needed. Verified by running eslint against the
    GAIA React reference app: the zones fire on app/** files and resolve the ~
    alias against the consumer root.

    Downstream impact (loud, but a minor by request): this is error-level and
    catches import type as well as value imports, so a consumer whose code
    currently crosses a layer boundary will see a NEW lint failure on upgrade. It
    is not auto-fixable; each hit is a real wrong-direction edge to relocate or an
    inline eslint-disable to add deliberately. The reference app surfaced exactly
    one edge across all of app/: a component importing a resource-route action
    type for useFetcher<typeof action>(). Treat such hits as signal, not noise.
    If a consumer relies on resource routes as a typed data-endpoint layer, relax
    only the components -> routes reach with the rule's except option rather
    than downgrading the rule.

  • #20 056d935 Thanks @stevensacks! - Harden the testing config with test-discipline rules beyond the
    @vitest/eslint-plugin recommended preset (all verified against plugin
    v1.6.19). These complement a mechanical TDD RED-verification gate by closing
    test-integrity gaps the gate cannot see on its own.

    Added (error):

    • consistent-test-it {fn: 'test'} — forbid mixing test()/it(); GAIA
      uses test() exclusively. fn cascades to within-describe in 1.6.19.
    • consistent-vitest-vi {fn: 'vi'} — forbid mixing the vitest/vi mock
      API; GAIA uses vi.
    • no-test-return-statement — a returned value/promise can resolve after the
      test "passes", faking GREEN.
    • no-conditional-in-test — a branch in a test body can assert nothing on one
      path. (Only this one; no-conditional-tests is a byte-identical duplicate.)
    • no-test-prefixes — forbid fdescribe/fit/xdescribe/xit, which bypass
      the active no-focused-tests / no-disabled-tests rules.
    • prefer-todo — push empty test('...') stubs to test.todo('...') so
      unimplemented tests are explicit, not silently passing. (Not warn-todo,
      which contradicts it.)
    • require-to-throw-message — a bare .toThrow() passes on any throw; require
      an asserted message or matcher.

    Changed (baseline bump):

    • no-disabled-tests warn -> error — .skip is the biggest gaming vector
      for a RED-verification gate. Park work with test.todo or an inline
      eslint-disable, not a silent .skip.

    Downstream impact: these are error-level, so projects with existing
    violations may see new lint failures. Most additions are auto-fixable
    (eslint --fix); no-disabled-tests and require-to-throw-message are not.
    Verified zero spurious fires across GAIA's 44 test/story files.