Skip to content
Merged
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
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,52 @@

Framework Doctor auto-detects your framework and runs the right health check. Supports **Svelte**, **React**, **Vue**, and **Angular**.

## Why this project exists

Framework teams usually rely on separate tools for linting, dead-code cleanup, dependency audits, and framework-specific checks. That creates fragmented output and slow feedback loops, especially in monorepos.

Framework Doctor was built to unify that workflow into one command:

- detect the framework automatically
- run the most relevant checks for that framework
- normalize findings into one diagnostic model
- compute a simple, comparable 0-100 score

The goal is pragmatic: give teams one health snapshot they can run locally, in PRs, or in CI without wiring several tools manually.

## Architecture overview

This repository is a TypeScript monorepo organized into framework-specific doctors plus shared core logic.

- `packages/core`
- shared scoring engine, shared diagnostic types, UI output helpers, security scan primitives, and telemetry helpers
- `packages/cli`
- unified entrypoint (`framework-doctor`) that detects or accepts a forced framework and dispatches to the matching doctor
- `packages/react-doctor`, `packages/vue-doctor`, `packages/svelte-doctor`, `packages/angular-doctor`
- framework adapters that run framework-relevant checks, map results to normalized diagnostics, and render output consistently
- `examples/`
- intentionally flawed sample apps for each framework
- `supabase/`
- optional telemetry backend schema and function

Each framework doctor follows the same high-level pipeline:

1. Discover project(s) and load config.
2. Run selected checks (lint/type/framework/security/dead-code/audit).
3. Normalize findings into common diagnostic fields.
4. Compute score with penalties by severity and volume.
5. Print text or JSON output and optionally emit telemetry.

## Feature highlights

- unified CLI with auto-detection and watch mode
- forced framework selection via `--framework <svelte|react|vue|angular>`
- monorepo project targeting with `--project`
- diff-only scanning via `--diff [base]`
- CI-friendly machine output with `--format json` and `--score`
- framework-aware checks plus common security and dependency audit checks
- optional, anonymous telemetry routed to your own Supabase endpoint

## Quick start

Run in a project root (auto-detects Svelte, React, Vue, Angular from `package.json`):
Expand Down Expand Up @@ -42,6 +88,7 @@ See [examples/README.md](examples/README.md) for more demo projects and commands
- `npx -y @framework-doctor/cli .` - auto-detect framework and run the right doctor
- `npx -y @framework-doctor/cli ./path/to/project` - scan a specific project directory
- `npx -y @framework-doctor/cli . --watch` - re-scan on file changes
- `npx -y @framework-doctor/cli . --framework react` - force a framework when detection is ambiguous or unavailable

**React (direct):**

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"typecheck": "turbo run typecheck --filter=./packages/*",
"test": "turbo run test --filter=./packages/*",
"test:doctor": "turbo run test --filter=@framework-doctor/svelte --concurrency=1",
"quality:check": "turbo run format:check lint typecheck test --filter=!./examples/*",
"quality:check": "turbo run format:check lint typecheck test --filter=./packages/*",
"changeset": "changeset",
"version": "changeset version",
"release": "pnpm build && changeset publish",
Expand Down
6 changes: 6 additions & 0 deletions packages/angular-doctor/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @framework-doctor/angular

## 1.1.1

### Patch Changes

- included more security rules

## 1.1.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/angular-doctor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@framework-doctor/angular",
"version": "1.1.0",
"version": "1.1.1",
"description": "Diagnose Angular codebase health",
"author": {
"name": "Pitis Radu",
Expand Down
2 changes: 1 addition & 1 deletion packages/angular-doctor/src/scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ export const scan = async (
: Promise.resolve<Diagnostic[]>([]);

const securityPromise = options.lint
? runSecurityScan(directory, includePaths)
? runSecurityScan(directory, includePaths, 'angular')
: Promise.resolve<Diagnostic[]>([]);

const [lintDiagnostics, deadCodeDiagnostics, securityDiagnostics] = await Promise.all([
Expand Down
16 changes: 14 additions & 2 deletions packages/angular-doctor/src/utils/run-security-scan.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import {
getFrameworkProfile,
HARDCODED_SECRET_RULES,
NO_BYPASS_SECURITY_TRUST_RULE,
NO_INNER_HTML_BINDING_RULE,
runProjectSecurityScan,
runSecurityScan as runSecurityScanCore,
SOURCE_FILE_PATTERN_WITH_ANGULAR,
UNIVERSAL_SECURITY_RULES,
Expand All @@ -10,13 +13,22 @@ const ANGULAR_PLUGIN = 'angular-doctor';

const ANGULAR_SECURITY_RULES = [
...UNIVERSAL_SECURITY_RULES,
...HARDCODED_SECRET_RULES,
NO_INNER_HTML_BINDING_RULE,
NO_BYPASS_SECURITY_TRUST_RULE,
];

export const runSecurityScan = async (rootDirectory: string, includePaths: string[]) =>
runSecurityScanCore(rootDirectory, includePaths, {
export const runSecurityScan = async (
rootDirectory: string,
includePaths: string[],
framework?: string,
) => {
const regexDiagnostics = await runSecurityScanCore(rootDirectory, includePaths, {
plugin: ANGULAR_PLUGIN,
rules: ANGULAR_SECURITY_RULES,
filePattern: SOURCE_FILE_PATTERN_WITH_ANGULAR,
});
const profile = framework ? getFrameworkProfile(ANGULAR_PLUGIN, framework) : null;
const projectDiagnostics = profile ? runProjectSecurityScan(rootDirectory, profile) : [];
return [...regexDiagnostics, ...projectDiagnostics];
};
11 changes: 11 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# @framework-doctor/cli

## 1.1.1

### Patch Changes

- included more security rules
- Updated dependencies
- @framework-doctor/angular@1.1.1
- @framework-doctor/svelte@1.1.1
- @framework-doctor/react@1.1.1
- @framework-doctor/vue@1.1.1

## 1.1.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@framework-doctor/cli",
"version": "1.1.0",
"version": "1.1.1",
"description": "Auto-detect framework and run the right doctor",
"author": {
"name": "Pitis Radu",
Expand Down
Loading