# TypeScript Project Setup Guide

Step-by-step guide to add Quality Rails to a TypeScript project.

## Prerequisites

- Node.js 18+ and npm/pnpm
- Git repository initialized
- TypeScript project (or create with `npm init` + `tsc --init`)

## Installation

### 1. Clone Quality Rails

```bash
git clone git@git.mosaicstack.dev:mosaic/quality-rails.git
```

### 2. Run Installation Script

```bash
# From your project directory
../quality-rails/scripts/install.sh --template typescript-node --target .
```

This copies:

- `.husky/pre-commit` - Git hooks (lint-staged + gitleaks)
- `.lintstagedrc.js` - Pre-commit checks
- `.eslintrc.js` - Strict ESLint rules
- `tsconfig.json` - TypeScript strict mode
- `.woodpecker.yml` - CI pipeline
- `.gitleaks.toml` - Secret scanning config

### 3. Install Dependencies

Add to your `package.json`:

```json
{
  "scripts": {
    "lint": "eslint 'src/**/*.{ts,tsx}' --max-warnings=0",
    "type-check": "tsc --noEmit",
    "test": "jest",
    "build": "tsc",
    "prepare": "husky install"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^7.0.0",
    "@typescript-eslint/parser": "^7.0.0",
    "eslint": "^9.0.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-prettier": "^5.0.0",
    "eslint-plugin-security": "^3.0.0",
    "husky": "^9.1.7",
    "jest": "^29.0.0",
    "lint-staged": "^16.2.7",
    "prettier": "^3.0.0",
    "typescript": "^5.6.0"
  }
}
```

Then run:

```bash
npm install
npx husky install
```

### 4. Verify Enforcement

```bash
../quality-rails/scripts/verify.sh
```

Should output:

```
✅ PASS: Type errors blocked
✅ PASS: 'any' types blocked
✅ PASS: gitleaks found (8.24.0)
✅ PASS: gitleaks detected planted secret
✅ PASS: Lint errors blocked
```

## What Gets Enforced

### TypeScript Strict Mode

All strict checks enabled in `tsconfig.json`:

```json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true
  }
}
```

### ESLint Rules

Key rules in `.eslintrc.js`:

```javascript
{
  '@typescript-eslint/no-explicit-any': 'error',              // Block 'any' types
  '@typescript-eslint/explicit-function-return-type': 'warn', // Require return types
  '@typescript-eslint/no-floating-promises': 'error',         // Catch unhandled promises
  '@typescript-eslint/no-misused-promises': 'error',          // Prevent promise misuse
}
```

### Pre-Commit Checks

On every `git commit`, runs:

1. ESLint with --max-warnings=0
2. TypeScript type check
3. Prettier formatting
4. Secret scanning via gitleaks (required)

If any fail → **commit blocked**.

## Troubleshooting

### "husky - pre-commit hook exited with code 1"

This means pre-commit checks failed. Read the error output:

```
src/example.ts:5:14 - error TS2322: Type 'number' is not assignable to type 'string'
```

Fix the error and commit again.

### "Cannot find module '@typescript-eslint/parser'"

Dependencies not installed:

```bash
npm install
```

### Pre-commit hooks not running

Husky not initialized:

```bash
npx husky install
```

## Customization

See [CUSTOMIZATION.md](./CUSTOMIZATION.md) for adjusting strictness levels.

## CI/CD Setup

See [CI-SETUP.md](./CI-SETUP.md) for Woodpecker/GitHub Actions configuration.
