|
|
||
|---|---|---|
| .forgejo/workflows | ||
| eslint | ||
| tsup | ||
| typescript | ||
| vite | ||
| vitest | ||
| .gitignore | ||
| CHANGELOG-2.1.0.md | ||
| package.json | ||
| README.md | ||
| TSCONFIG_PATH_RESOLUTION_FIX.md | ||
@lilith/configs
Unified configuration package for ESLint, TypeScript, Vite, and Vitest. Provides opinionated, production-ready defaults for the Lilith Platform ecosystem.
Features
- Strict by default: TypeScript strict mode, ESLint errors not warnings
- Modern tooling: ES2022, React 19+, Vite 5+, Vitest 2+
- Consistent formatting: Python-like whitespace and blank line rules
- Framework-specific: Presets for React, NestJS, and Node.js
- Minimal configuration: Single-line setup for each tool
- Dev console integration: Optional auto-injection of debugging helpers
Installation
pnpm add -D @lilith/configs
Quick Start
ESLint
// eslint.config.js
module.exports = require('@lilith/configs/eslint/react');
TypeScript
{
"extends": "@lilith/configs/typescript/react"
}
Vite
// vite.config.ts
import { createViteConfig } from '@lilith/configs/vite/react';
export default createViteConfig({ port: 3000 });
Vitest
// vitest.config.ts
import { createVitestReactConfig } from '@lilith/configs/vitest/react';
export default createVitestReactConfig();
ESLint Configurations
Available Presets
| Import Path | Function | Use Case | Requires tsconfigRootDir |
|---|---|---|---|
@lilith/configs/eslint/base |
(legacy, CommonJS) | Node.js packages | No |
@lilith/configs/eslint/base-flat |
createBaseConfig() |
Node.js packages (ESM) | Yes |
@lilith/configs/eslint/react |
(legacy, CommonJS) | React applications | No |
@lilith/configs/eslint/react-flat |
createReactConfig() |
React applications (ESM) | Yes (when typeAware=true) |
@lilith/configs/eslint/nestjs |
(legacy, CommonJS) | NestJS services | No |
@lilith/configs/eslint/nestjs-flat |
createNestJSConfig() |
NestJS services (ESM) | Yes |
Usage
Legacy CommonJS (Deprecated)
// eslint.config.js
module.exports = require('@lilith/configs/eslint/react');
Modern ESM Flat Config (Recommended)
NestJS Backend Services:
// eslint.config.js
import tseslint from 'typescript-eslint';
import { createNestJSConfig } from '@lilith/configs/eslint/nestjs-flat';
export default tseslint.config(
...createNestJSConfig({
tsconfigRootDir: import.meta.dirname, // REQUIRED
})
);
React Applications:
// eslint.config.js
import tseslint from 'typescript-eslint';
import { createReactConfig } from '@lilith/configs/eslint/react-flat';
export default tseslint.config(
...createReactConfig({
tsconfigRootDir: import.meta.dirname, // REQUIRED
})
);
Node.js Packages:
// eslint.config.js
import tseslint from 'typescript-eslint';
import { createBaseConfig } from '@lilith/configs/eslint/base-flat';
export default tseslint.config(
...createBaseConfig({
tsconfigRootDir: import.meta.dirname, // REQUIRED
})
);
With Custom Overrides:
import tseslint from 'typescript-eslint';
import { createNestJSConfig } from '@lilith/configs/eslint/nestjs-flat';
export default tseslint.config(
...createNestJSConfig({
tsconfigRootDir: import.meta.dirname,
tsconfigPath: './tsconfig.lint.json', // Optional: custom tsconfig
}),
// Add project-specific rules
{
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
);
CRITICAL: The tsconfigRootDir: import.meta.dirname parameter is required for type-aware linting to work correctly. Without it, TypeScript parser will try to find tsconfig.json in the @lilith/configs package directory instead of your project directory.
Technical Details: Path Resolution
When using shared ESLint configs with TypeScript parser in a flat config setup:
- The Problem:
import.meta.dirnameis evaluated in the context of where the JavaScript module is loaded from, not where it's defined - Why it matters: The TypeScript parser needs to know where to find your project's
tsconfig.json - The Solution: Pass
import.meta.dirnameas a parameter from the consuming project'seslint.config.js
This ensures the path is evaluated in your project directory, not inside node_modules/@lilith/configs/.
Example of broken usage (DO NOT DO THIS):
// WRONG - will look for tsconfig in @lilith/configs package
import nestjsConfig from '@lilith/configs/eslint/nestjs-flat';
export default nestjsConfig; // Missing tsconfigRootDir parameter!
Included Rules
Base preset includes:
- TypeScript strict checking
- Import order/sorting
- Prettier integration
- No unused variables/imports
- Consistent spacing
React preset adds:
- React hooks rules
- JSX accessibility (a11y)
- React-specific best practices
NestJS preset adds:
- Decorator support
- Dependency injection patterns
TypeScript Configurations
Available Presets
| Import Path | Target | Features |
|---|---|---|
@lilith/configs/typescript/base |
Node.js | Strict, NodeNext modules |
@lilith/configs/typescript/esm |
Universal | ESM, bundler resolution |
@lilith/configs/typescript/react |
Browser | JSX, DOM types |
@lilith/configs/typescript/nestjs |
Node.js | Decorators, emit metadata |
Usage
// tsconfig.json
{
"extends": "@lilith/configs/typescript/react",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*"]
}
Base Configuration Details
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
// Strict mode (all enabled)
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"alwaysStrict": true,
// Code quality
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
// Output
"declaration": true,
"declarationMap": true,
"sourceMap": true,
// Interop
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true
}
}
Vite Configuration
API
import { createViteConfig } from '@lilith/configs/vite/react';
export default createViteConfig(options);
ViteConfigOptions
| Option | Type | Default | Description |
|---|---|---|---|
port |
number |
3000 |
Dev server port |
plugins |
Plugin[] |
[] |
Additional Vite plugins |
resolve |
ResolveOptions |
{} |
Module resolution options |
build |
BuildOptions |
{} |
Build options |
devConsole |
boolean | DevConsoleOptions |
true |
Enable dev console helpers |
DevConsoleOptions
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
true in dev |
Enable/disable |
namespace |
string |
'dev' |
Window namespace |
Examples
// Basic usage
export default createViteConfig({ port: 3000 });
// With custom plugins
import tsconfigPaths from 'vite-tsconfig-paths';
export default createViteConfig({
port: 5173,
plugins: [tsconfigPaths()],
});
// Disable dev console
export default createViteConfig({
devConsole: false,
});
// Custom dev console namespace
export default createViteConfig({
devConsole: { namespace: 'debug' },
});
Built-in Features
- React plugin pre-configured
- Strict port binding
- Source maps enabled
- Vendor chunk splitting (react, react-dom)
- Auto-load
@lilith/dev-consoleif installed
Vitest Configuration
React Testing
import { createVitestReactConfig } from '@lilith/configs/vitest/react';
export default createVitestReactConfig(options);
Options:
| Option | Type | Default | Description |
|---|---|---|---|
include |
string[] |
['src/**/*.test.{ts,tsx}', 'src/**/*.spec.{ts,tsx}'] |
Test file patterns |
exclude |
string[] |
['node_modules', 'dist'] |
Exclude patterns |
setupFiles |
string[] |
[] |
Setup files to run before tests |
coverage |
CoverageOptions |
{} |
Coverage configuration |
Defaults:
- Environment:
jsdom - Globals:
true - CSS support:
true - Coverage: v8 provider with text, json, html reporters
Node.js Testing
import { createVitestNodeConfig } from '@lilith/configs/vitest/node';
export default createVitestNodeConfig(options);
Options:
| Option | Type | Default | Description |
|---|---|---|---|
include |
string[] |
['src/**/*.test.ts', 'src/**/*.spec.ts'] |
Test file patterns |
exclude |
string[] |
['node_modules', 'dist'] |
Exclude patterns |
coverage |
CoverageOptions |
{} |
Coverage configuration |
Defaults:
- Environment:
node - Globals:
true - Coverage: v8 provider with text, json, html reporters
Examples
// React with setup file
export default createVitestReactConfig({
setupFiles: ['./src/test/setup.ts'],
});
// Node with custom coverage
export default createVitestNodeConfig({
coverage: {
threshold: {
lines: 80,
branches: 80,
},
},
});
// Custom include patterns
export default createVitestReactConfig({
include: ['tests/**/*.test.tsx'],
exclude: ['node_modules', 'dist', 'e2e'],
});
Philosophy
Strict TypeScript
All TypeScript strict flags enabled. No any types slip through.
Formatting
Prettier handles formatting. ESLint handles logic. No conflicts.
Modern Defaults
- ES2022 target (top-level await, private fields)
- ESM modules
- React 19+ concurrent features
- Vite 5+ bundler
Minimal Boilerplate
// Complete React app config in 4 files:
// tsconfig.json
{ "extends": "@lilith/configs/typescript/react" }
// eslint.config.js
module.exports = require('@lilith/configs/eslint/react');
// vite.config.ts
import { createViteConfig } from '@lilith/configs/vite/react';
export default createViteConfig();
// vitest.config.ts
import { createVitestReactConfig } from '@lilith/configs/vitest/react';
export default createVitestReactConfig();
Peer Dependencies
Required for all configs:
eslint >= 9.0.0typescript >= 5.0.0@typescript-eslint/parser >= 8.0.0@typescript-eslint/eslint-plugin >= 8.0.0eslint-plugin-import >= 2.26.0eslint-plugin-prettier >= 5.0.0eslint-config-prettier >= 9.0.0prettier >= 3.0.0
Optional (for specific configs):
eslint-plugin-react(React)eslint-plugin-react-hooks(React)eslint-plugin-jsx-a11y(React)@vitejs/plugin-react(Vite)vite(Vite)vitest(Vitest)@lilith/dev-console(dev console helpers)
License
MIT