@stride.it/appoint-lint-governance
v0.1.33
Published
Shareable ESLint flat-config profiles (MVP: TypeScript) for normalizing lint across repos.
Maintainers
Readme
@stride.it/appoint-lint-governance
Shareable ESLint v9 flat-config builders to normalize linting across repositories.
This package provides two domains:
- TypeScript domain: framework-agnostic TypeScript quality gates (correctness, imports hygiene, security, maintainability, and optional type-aware checks).
- Framework domain: React + Next.js + Accessibility (a11y) presets.
Everything is designed to be composed in consumer repos (flat config is order-dependent); this is not an all-or-nothing mega-config.
What you get
- Composable flat-config builders (arrays of ESLint config objects).
- A minimal baseline for fast adoption.
- A recommended preset that composes the major rule groups.
- Optional type-aware rules (requires a TSConfig project).
- Optional Prettier interop preset to disable formatting-rule conflicts.
Non-goals:
- No test-runner targeting (Vitest/Jest/Playwright rules are out of scope for now).
- No formatting (Prettier remains the formatter; ESLint formatting conflicts are disabled via the interop preset).
Install
In a consumer repo:
pnpm add -D @stride.it/appoint-lint-governance eslintESLint is a peer dependency; your repo owns the ESLint version.
Quick start (ESLint v9 flat config)
Create (or edit) eslint.config.mjs:
import { typescriptMinimal } from "@stride.it/appoint-lint-governance";
export default [...typescriptMinimal()];Run ESLint in your repo as usual:
pnpm lintPublic API
These builders return arrays you spread into your eslint.config.*:
typescriptBase(options?)
Baseline correctness + safe defaults (files globs, languageOptions).typescriptMinimal(options?)
Minimal preset (fast adoption baseline).typescriptRecommended(options?)
Recommended preset that composes core groups and can optionally enable type-aware rules.typescriptPrettierInterop(options?)
Disables formatting-rule conflicts when the consumer repo uses Prettier.
Framework domain builders/presets:
react(options?),reactRecommendeda11y(options?),a11yRecommendednextjs(options?),nextjsRecommended(composes React + A11y + Next rules)
Additionally:
plugin
Optional plugin export used by internal configs.
Recommended preset (most repos)
import { typescriptRecommended } from "@stride.it/appoint-lint-governance";
export default [...typescriptRecommended()];Type-aware linting (optional)
Type-aware rules can catch issues ESLint cannot detect from syntax alone (for example: misused promises, unsafe operations). They require a TSConfig project.
import { typescriptRecommended } from "@stride.it/appoint-lint-governance";
export default [
...typescriptRecommended({
typeChecked: true,
tsconfigPath: "./tsconfig.json",
tsconfigRootDir: import.meta.dirname,
// Optional: fail CI on deprecated APIs surfaced by type definitions
reportDeprecated: true,
}),
];If your Node.js version does not support import.meta.dirname, use this portable alternative:
import { fileURLToPath } from "node:url";
const tsconfigRootDir = fileURLToPath(new URL(".", import.meta.url));Then pass tsconfigRootDir into typescriptRecommended({ ... }).
Framework domain examples (React / A11y / Next.js)
A) Domain linting (simple): Next.js preset
Use this when you want “framework linting” as a single preset. This includes React + A11y + Next.js rules.
import { nextjsRecommended, typescriptRecommended } from "@stride.it/appoint-lint-governance";
export default [
...typescriptRecommended({
typeChecked: true,
tsconfigPath: "./tsconfig.json",
tsconfigRootDir: import.meta.dirname,
}),
...nextjsRecommended,
];B) Domain linting (explicit): one line per domain
Use this when you want React / A11y / Next.js as separate “domain lines”.
Important: do not use nextjsRecommended together with reactRecommended and a11yRecommended (it would duplicate rules).
import {
a11yRecommended,
nextjs,
reactRecommended,
typescriptRecommended,
} from "@stride.it/appoint-lint-governance";
export default [
...typescriptRecommended({
typeChecked: true,
tsconfigPath: "./tsconfig.json",
tsconfigRootDir: import.meta.dirname,
}),
...reactRecommended,
...a11yRecommended,
...nextjs(),
];C) Running domains independently (separate configs)
Flat config is a single array, but you can run “per-domain” by creating multiple config files and selecting them with eslint --config.
Example scripts:
{
"scripts": {
"lint:ts": "eslint --config ./eslint.typescript-only.config.mjs \"src/**/*.{ts,tsx}\"",
"lint:react": "eslint --config ./eslint.react-only.config.mjs \"src/**/*.{tsx,jsx}\"",
"lint:a11y": "eslint --config ./eslint.a11y-only.config.mjs \"src/**/*.{tsx,jsx}\"",
"lint:next": "eslint --config ./eslint.nextjs-only.config.mjs \"src/**/*.{tsx,jsx}\""
}
}Prettier interop (optional)
If your project uses Prettier, include the interop preset last so it can override earlier formatting rules:
import {
typescriptPrettierInterop,
typescriptRecommended,
} from "@stride.it/appoint-lint-governance";
export default [
...typescriptRecommended(),
...typescriptPrettierInterop(),
];Overriding rules in consumer repos
Flat config is order-dependent: later entries win. Consumers can override by appending their own config object after spreading a preset.
If your organization wants to prevent overrides, ESLint itself cannot lock consumer rules; enforce that with CI/policy checks on the consumer repo’s eslint.config.*.
Suggested companion quality gates (outside ESLint)
This package intentionally focuses on ESLint rules. Many teams also enforce these CI gates:
- Type checking:
tsc --noEmit - Dependency audit:
pnpm audit(or your org-approved alternative) - Secret scanning and SAST (org-dependent)
Development (this repo)
pnpm install
pnpm test
pnpm buildTo validate the publish output locally:
npm packThen install the generated .tgz into a consumer repo.
Publishing
- Bump version:
pnpm version patch- Dry run:
pnpm publish --dry-run- Publish (requires npm credentials with access to the
@stride.itscope):
pnpm publish --access public