Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v7
with:
node-version: 22.x
node-version: 24.x
cache: npm
- run: npm ci
- name: linting
Expand All @@ -23,7 +23,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [20.x, 22.x]
node-version: [22.x, 24.x]
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v7
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nodejs 22.22.1
nodejs 24.21.0
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ npm install --save-dev @heroku-cli/test-utils

## Requirements

- Node.js >= 20
- TypeScript >= 5.4.0
- Node.js >= 22.12
- TypeScript >= 6 (required by the shared ESLint config; see [ESLint Configuration](#eslint-configuration))
- ESM (ES Modules) support
- A test runner of your choice (Mocha and Vitest are both supported)

## ESLint Configuration

This package provides a shareable ESLint 9 flat config that extends oclif's base configuration with Heroku-specific rules. The base config is test-framework-agnostic; layer on the `mocha` or `vitest` overlay depending on what your repo uses.
This package provides a shareable ESLint 10 flat config that extends oclif's base configuration with Heroku-specific rules. The base config is test-framework-agnostic; layer on the `mocha` or `vitest` overlay depending on what your repo uses.

### Setup

1. Install the required peer dependencies:
```bash
npm install --save-dev eslint@^9 eslint-config-oclif@^6
npm install --save-dev eslint@^10 eslint-config-oclif@^7
# vitest repos also need:
npm install --save-dev eslint-plugin-vitest
npm install --save-dev @vitest/eslint-plugin
```

2. Create `eslint.config.js` in your project root:
Expand Down Expand Up @@ -63,6 +63,10 @@ export default [
]
```

> **Note:** As of `eslint-config-oclif` 7, the config uses type-aware linting (`projectService`). ESLint must be able to resolve every linted file through a `tsconfig.json`, so make sure your test files (and root config files such as `vitest.config.ts`) are covered by your tsconfig's `include` — files outside the TypeScript project fail with a `was not found by the project service` parse error. If you build from the same tsconfig, keep a separate `tsconfig.build.json` that only includes `src` so test files aren't emitted to your published output.
>
> **TypeScript 6 required:** `eslint-config-oclif` 7 (via `eslint-config-xo`) declares a `typescript >=6` peer dependency. If your project is still on TypeScript 5, npm will install a *second*, nested TypeScript 6 for the lint stack, and the version skew crashes type-aware rules with `tsutils.unionConstituents is not a function`. Pin a single TypeScript `~6.0` at your project root (and, if needed, add `"overrides": { "typescript": "$typescript" }`) so the whole lint stack resolves one TypeScript. Note that TypeScript 6 requires an explicit `rootDir` in build configs that previously inferred it.

### What's Included

The base configuration includes:
Expand All @@ -76,7 +80,7 @@ The base configuration includes:

The `mocha` overlay is optional — the base config already passes through oclif's mocha-plugin defaults. Importing it bumps `mocha/no-exclusive-tests` from `warn` to `error` so a stray `it.only` fails CI.

The `vitest` overlay adds `eslint-plugin-vitest`'s recommended rules and globals for test files, and globally disables every `mocha/*` rule. (The mocha plugin itself is loaded transitively via `eslint-config-oclif` and can't be unregistered in flat config — but the overlay neutralizes its rules so they produce zero diagnostics.)
The `vitest` overlay adds `@vitest/eslint-plugin`'s recommended rules and globals for test files, and globally disables every `mocha/*` rule. (The mocha plugin itself is loaded transitively via `eslint-config-oclif` and can't be unregistered in flat config — but the overlay neutralizes its rules so they produce zero diagnostics.)

## Usage

Expand Down
4 changes: 3 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import base from './src/eslint-config/index.js'
import vitest from './src/eslint-config/vitest.js'

export default [...base, ...vitest]
const config = [...base, ...vitest]

export default config
Loading
Loading