npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

native-doctor

v0.8.0

Published

An evidence-based project health scanner for React Native, Expo and React apps. Combines React Doctor & Native Doctor capabilities with AST symbol graphs, architecture analysis and official platform guidance.

Readme

native-doctor

Unified React & Native Project Intelligence Engine for React Native, Expo, and React apps.

Combines full React Doctor (Hooks rules, Component lifecycle, JSX reconciliation, State duplication) and Native Doctor (Android 14+ foreground services, Apple App Store privacy keys, Target SDK 34+, New Architecture, Audio state authority) into a single, unified static analysis tool.

Is this project implemented the official, minimal, platform-correct way — or does it carry unnecessary/legacy/AI-generated complexity?

Every finding answers:

  • WHAT was found (precise file location and line numbers)
  • WHY it is a problem (coupling, performance, security, architecture)
  • OFFICIAL platform requirement / guideline (React, React Native, Android, Apple, Expo)
  • DO NOT guidance (explicit warnings on what anti-patterns NOT to add)
  • FIX (the smallest direct change, with safe --fix automation where possible)
  • PRIORITY (P0 Critical $\rightarrow$ P1 Warning $\rightarrow$ P2 Tech Debt $\rightarrow$ P3 Complexity Review)

Quick Execution

# Unified React + React Native scan
npx native-doctor@latest

# Deep architectural graph & target roadmap
npx native-doctor@latest --deep

# Focus specifically on React core & hooks (React Doctor mode)
npx native-doctor@latest --react

# Focus specifically on Native config & permissions (Native Doctor mode)
npx native-doctor@latest --native

# Auto-fix safe issues
npx native-doctor@latest --fix

native-doctor --performance native-doctor --accessibility native-doctor --native native-doctor --audio --plan

Run without interactive TTY prompt

native-doctor --no-interactive


---

## Diagnostic Rules Catalog (v0.1.0)

| Category | Rule ID | What It Checks |
|---|---|---|
| **ui** | `RNDOCTOR-UI-021` | `TouchableOpacity` usage that should migrate to `Pressable` |
| **accessibility** | `RNDOCTOR-A11Y-001` | Self-closing interactive touchables missing `accessibilityLabel` |
| **code** | `RNDOCTOR-CODE-040` | Scope-analyzed unused imports (with zero false-positives on React JSX runtime) |
| **code** | `RNDOCTOR-CODE-050` | `console.*` debug statements left in application code |
| **code** | `RNDOCTOR-PLATFORM-010` | Heavy inline `Platform.OS` branching that should move to `.ios.js` / `.android.js` |
| **code** | `RNDOCTOR-CODE-110` | Unnecessary `useMemo` / `useCallback` with empty deps and a trivial body |
| **code** | `RNDOCTOR-CODE-103` | Direct `async` callback passed to `useEffect` (unhandled promise leak) |
| **code** | `RNDOCTOR-CODE-104` | `useState` + `useEffect` loading state boilerplate tracking a single async call |
| **code** | `RNDOCTOR-PERF-011` | Uncontrolled `setInterval` timer polling |
| **correctness** | `RNDOCTOR-SYNTAX-001` | Syntax or AST parse errors in JavaScript / TypeScript / JSX files |
| **architecture** | `RNDOCTOR-FILE-031` | `services/`, `utils/`, or `api/` layers importing UI screens or navigation |
| **architecture** | `RNDOCTOR-ARCH-001` | Circular module import cycles across source files |
| **architecture** | `AUDIO-ARCH-001` | Overlapping playback-state authority across multiple modules |
| **architecture** | `AUDIO-IOS-003` | Multiple `AVAudioSession` configurations across native iOS files |
| **native** | `RNDOCTOR-NATIVE-005` | Android native modules extending legacy `ReactContextBaseJavaModule` |
| **native** | `RNDOCTOR-NATIVE-017` | Android manifest permissions declared without matching dependencies |
| **native** | `RNDOCTOR-NATIVE-001` | Legacy Android storage permissions (`READ/WRITE_EXTERNAL_STORAGE`) |
| **native** | `RNDOCTOR-CONFIG-201` | Application / bundle ID mismatches between `app.json`, Android, and Xcode |
| **native** | `RNDOCTOR-NATIVE-030` | New Architecture flag mismatch across `app.json`, `gradle.properties`, and `Podfile` |
| **native** | `AUDIO-ANDROID-004` | Legacy Android `MediaPlayer` / `MediaExtractor` usage instead of Android Media3 |
| **security** | `RNDOCTOR-SECURITY-012` | Hardcoded API keys, private tokens, or secrets committed in client code |
| **security** | `RNDOCTOR-SECURITY-021` | Insecure non-localhost `http://` URLs in client code |
| **security** | `RNDOCTOR-ANDROID-SEC-002` | Android `usesCleartextTraffic='true'` enabled in release manifests |
| **dependencies** | `RNDOCTOR-DEP-001` | Known deprecated/renamed packages (e.g. `@react-native-community/async-storage`, `react-navigation`) |
| **dependencies** | `RNDOCTOR-DEP-010` | Packages accidentally listed in both `dependencies` and `devDependencies` |
| **config** | `RNDOCTOR-CONFIG-001` | Missing or invalid `package.json` |
| **config** | `RNDOCTOR-CONFIG-050` | Duplicate plugin/preset entries in `babel.config.js` |
| **config** | `RNDOCTOR-EXPO-001` | Expo dependency and native directories without root app configuration |
| **performance** | `AUDIO-PROGRESS-007` | Playback position interval polling and event subscriptions conflicting |

---

## Configuration (`native-doctor.config.json`)

You can customize rules and ignore files by creating a `native-doctor.config.json` in your project root:

```json
{
  "ignore": [
    "src/legacy/**",
    "**/*.test.ts"
  ],
  "rules": {
    "RNDOCTOR-UI-021": "off",
    "RNDOCTOR-CODE-050": "warning",
    "RNDOCTOR-SECURITY-012": "error"
  }
}

Programmatic API

import { runScan, applyFixes, buildContext } from "native-doctor";

// Run scan on a directory
const report = await runScan({ dir: "./my-app" });
console.log(`Overall Health: ${report.score.overall}/100`);
console.log(`Found ${report.findings.length} findings.`);

// Apply safe AST fixes
const fixResults = applyFixes(report.findings);
console.log(`Applied ${fixResults.filter(f => f.applied).length} fixes.`);

Architecture & Design Principles

  1. Deterministic AST First: Full parsing via @babel/parser and @babel/traverse with TypeScript & JSX support.
  2. Zero False Positives Priority: Rules account for JSX runtimes, dev configs, and platform branching.
  3. Safe AST Transformations: --fix alters only exact AST ranges without regex corruption.
  4. CI & Automation Ready: Non-zero exit code on errors, clean JSON reporting.

License

MIT