chore(13-01): install ESLint+Prettier, author flat config, wire lint/format scripts
- Install eslint@9.39.4 @eslint/js@9.39.4 typescript-eslint@8.61.0 eslint-plugin-react@7.37.5 eslint-plugin-react-hooks@7.1.1 eslint-config-prettier@10.1.8 prettier@3.8.4 as root devDependencies - Author eslint.config.js: ignores → base recommendedTypeChecked (projectService:true) → pwa-react block (apps/pwa/** only) → disableTypeChecked override (config files + apps/api/tests) → prettier-last (eslint-config-prettier/flat) - Add .prettierrc (singleQuote:true, printWidth:100) and .prettierignore - Add "type":"module" to root package.json; add format/format:check scripts - Add lint script (--max-warnings 0) to apps/api and apps/pwa
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
|
pnpm-lock.yaml
|
||||||
|
apps/api/src/db/migrations/
|
||||||
|
*.html
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"printWidth": 100
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
|
"lint": "eslint src/ tests/ --max-warnings 0",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"db:generate": "drizzle-kit generate",
|
"db:generate": "drizzle-kit generate",
|
||||||
"db:migrate": "drizzle-kit migrate"
|
"db:migrate": "drizzle-kit migrate"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint src/ e2e/ --max-warnings 0",
|
||||||
"typecheck": "tsc --noEmit && tsc --project tsconfig.e2e.json --noEmit",
|
"typecheck": "tsc --noEmit && tsc --project tsconfig.e2e.json --noEmit",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:e2e": "playwright test",
|
"test:e2e": "playwright test",
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// eslint.config.js — root flat ESLint config (ESM)
|
||||||
|
// Covers: apps/api (Node/TS) + apps/pwa (React 19 + TypeScript)
|
||||||
|
// typescript-eslint v8, projectService: true (auto-discovers all tsconfigs)
|
||||||
|
// ESLint pinned to 9.39.4 — do NOT upgrade to ESLint 10 until eslint-plugin-react
|
||||||
|
// resolves the "getFilename is not a function" incompatibility (jsx-eslint#3977).
|
||||||
|
|
||||||
|
import js from '@eslint/js'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import reactPlugin from 'eslint-plugin-react'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import prettierConfig from 'eslint-config-prettier/flat'
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
// ── 1. Global ignores (replaces .eslintignore) ────────────────────────────
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'**/dist/**', // build output: apps/api/dist, apps/pwa/dist, generated sw.js
|
||||||
|
'**/node_modules/**',
|
||||||
|
'apps/api/src/db/migrations/**', // generated Drizzle SQL files
|
||||||
|
'pnpm-lock.yaml',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── 2. Base: all TS/TSX files in both apps ────────────────────────────────
|
||||||
|
// Uses recommendedTypeChecked (type-aware) per D-13-01.
|
||||||
|
// NOT strict/strictTypeChecked — D-13-03 explicitly rejects the extra churn.
|
||||||
|
{
|
||||||
|
files: ['apps/**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommendedTypeChecked,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
projectService: true,
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// Allow _-prefixed names as intentionally unused (params + vars)
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── 3. React + Hooks: PWA only (D-13-02) ────────────────────────────────
|
||||||
|
// Apps/api is Node/TS only — React config does NOT apply there.
|
||||||
|
{
|
||||||
|
files: ['apps/pwa/**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
reactPlugin.configs.flat.recommended,
|
||||||
|
reactHooks.configs.flat.recommended,
|
||||||
|
],
|
||||||
|
settings: {
|
||||||
|
react: { version: 'detect' },
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// TypeScript props typing supersedes prop-types in React 19 (RESEARCH Open Question 2)
|
||||||
|
'react/prop-types': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── 4. disableTypeChecked override (D-13-10) ─────────────────────────────
|
||||||
|
// These files are outside all tsconfig projects (tool configs + API test dir).
|
||||||
|
// projectService: true cannot type-check them → disable type-aware rules only.
|
||||||
|
// Non-type-aware rules (syntax, no-unused-vars) still apply.
|
||||||
|
// Source: typescript-eslint.io/troubleshooting/typed-linting/#i-get-errors-telling-me-the-file-must-be-included
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'apps/api/drizzle.config.ts',
|
||||||
|
'apps/api/vitest.config.ts',
|
||||||
|
'apps/pwa/vite.config.ts',
|
||||||
|
'apps/pwa/vitest.config.ts',
|
||||||
|
'apps/pwa/playwright.config.ts',
|
||||||
|
'apps/api/tests/**/*.ts', // excluded from apps/api/tsconfig.json (Pitfall 2)
|
||||||
|
'eslint.config.js', // this file itself (not a ts project member)
|
||||||
|
],
|
||||||
|
extends: [tseslint.configs.disableTypeChecked],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── 5. eslint-config-prettier: MUST BE LAST ──────────────────────────────
|
||||||
|
// Disables all ESLint formatting rules that conflict with Prettier (D-13-07).
|
||||||
|
// Use the /flat import path for ESM flat config (Pitfall 7).
|
||||||
|
// Source: github.com/prettier/eslint-config-prettier
|
||||||
|
prettierConfig,
|
||||||
|
)
|
||||||
+13
-1
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "familysync",
|
"name": "familysync",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"packageManager": "pnpm@11.5.1",
|
"packageManager": "pnpm@11.5.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:api": "pnpm --filter @familysync/api dev",
|
"dev:api": "pnpm --filter @familysync/api dev",
|
||||||
@@ -9,6 +10,17 @@
|
|||||||
"test": "pnpm --filter @familysync/api test",
|
"test": "pnpm --filter @familysync/api test",
|
||||||
"test:e2e": "pnpm --filter @familysync/pwa test:e2e",
|
"test:e2e": "pnpm --filter @familysync/pwa test:e2e",
|
||||||
"lint": "pnpm -r --if-present lint",
|
"lint": "pnpm -r --if-present lint",
|
||||||
"typecheck": "pnpm -r typecheck"
|
"typecheck": "pnpm -r typecheck",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"format:check": "prettier --check ."
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "9.39.4",
|
||||||
|
"eslint": "9.39.4",
|
||||||
|
"eslint-config-prettier": "10.1.8",
|
||||||
|
"eslint-plugin-react": "7.37.5",
|
||||||
|
"eslint-plugin-react-hooks": "7.1.1",
|
||||||
|
"prettier": "3.8.4",
|
||||||
|
"typescript-eslint": "8.61.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1085
-1
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user