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

@autotracer/inject-react18

v1.0.0-alpha.35

Published

Shared AST transform logic for auto-injecting useReactTracer

Readme

@autotracer/inject-react18

Core AST transformation engine for automatic React component instrumentation.

This package provides the shared transformation logic used by all ReactTracer build plugins. It analyzes your React components and automatically injects tracing hooks—you typically don't use this directly unless building custom tooling.

What You Get

  • AST-based transformation - Safe, non-destructive code injection
  • Component detection - Identifies React components automatically
  • Hook labeling - Extracts variable names from useState, useReducer, custom hooks
  • Pragma support - Function-level control (@trace, @trace-disable per component)
  • Plugin foundation - Powers Vite and Babel plugins

Who This Is For

This is a low-level library for build tool authors. If you're using Vite or Next.js, use the dedicated plugins instead:

Overview

This package provides the core Babel AST transformation functionality used by the Auto Tracer ecosystem to automatically inject tracing hooks into React components. It analyzes TypeScript/JSX code, identifies React components, and injects useReactTracer initialization along with labelState calls for configured hooks.

Features

  • Automatic Component Detection: Identifies React function components, arrow functions, and HOC-wrapped components
  • Hook Labeling: Injects labelState calls for useState, useReducer, and configured custom hooks
  • Function-Level Pragma Support: Respects per-component tracing control pragmas (@trace, @trace-disable)
  • TypeScript Support: Full TypeScript and JSX parsing support
  • Safe AST Manipulation: Uses Babel's traversal API for safe, non-destructive code transformations

Component Detection Strategy

ReactTracer uses a multi-layer defense system to accurately identify React components while avoiding false positives. This ensures only genuine components receive instrumentation.

Detection Layers

Layer 1: Rejection - Explicit Non-Components

Functions in these contexts are never treated as components:

  • React.lazy(() => import(...)) - Module loaders
  • promise.then(() => ...) - Promise callbacks
  • array.map((item) => ...) - Array method callbacks
  • setTimeout(() => ...) - Timing callbacks
  • addEventListener(() => ...) - Event handlers
  • ALL async functions - Server Components, data loaders, utilities (hooks don't work in async)

Layer 2: Signal Detection - Component Indicators

At least ONE of these signals is required:

  • Returns JSX elements (<div>...</div>) or fragments (<>...</>)
  • Calls React hooks (useState, useEffect, custom hooks)
  • Contains JSX anywhere in function body

Layer 3: Validation - Structure

Additional requirements:

  • Top-level declarations (not nested functions)
  • Function declaration, arrow function, or function expression
  • No naming restrictions - Both PascalCase and camelCase accepted

Supported Patterns

// ✅ Function declarations with JSX
function Button() {
  return <button>Click</button>;
}

// ✅ Arrow functions with JSX
const Card = () => <div>Card</div>;

// ✅ Components with hooks
const Form = () => {
  const [value, setValue] = useState("");
  return <input value={value} />;
};

// ✅ HOC-wrapped components
const MemoButton = memo(() => <button>Memo</button>);
const RefInput = forwardRef((props, ref) => <input ref={ref} />);

// ✅ Conditional JSX
function Conditional({ show }) {
  if (show) return <div>Visible</div>;
  return null;
}

// ✅ camelCase components with JSX
const renderHeader = () => <header>Title</header>;

// ✅ camelCase components with hooks
const useCustomComponent = () => {
  const [state] = useState();
  return <div>{state}</div>;
};

Rejected Patterns

// ❌ React.lazy() loader (not a component)
const Lazy = lazy(() => import("./Component"));

// ❌ Promise callbacks
fetch("/api").then((res) => res.json());

// ❌ Array methods (even with JSX)
items.map((item) => <li key={item.id}>{item.name}</li>);

// ❌ ALL async functions (even with JSX - hooks don't work in async)
async function ServerData() {
  const data = await fetchData();
  return <div>{data}</div>;
}

// ❌ Async utilities
async function fetchUserData(id) {
  return await fetch(`/api/users/${id}`).then((r) => r.json());
}

// ❌ Utilities without JSX or hooks
const parseJSON = (str) => JSON.parse(str);
const calculateTotal = (items) => items.reduce((sum, i) => sum + i.price, 0);

// ❌ Event handlers
setTimeout(() => console.log("tick"), 1000);

Manual Override

If detection fails for your component, use pragmas:

// Force enable (opt-in mode)
// @trace
const unusualComponent = customWrapper(() => <div />);

// Force disable (even if has JSX/hooks)
// @trace-disable
const utilityWithJSX = () => <div>Template</div>;

Architecture

The transformation pipeline processes your source code through several stages:

graph TD
    A[Source Code] --> B[Babel Parser]
    B --> C[AST Analysis]
    C --> D[Component Detection]
    D --> E[Hook Scanning]
    E --> F[AST Injection]
    F --> G[Code Generation]
    G --> H[Transformed Code]

    D --> I{Pragma Check}
    I --> J[Skip if disabled]
    I --> K[Continue if enabled]

    E --> L[useState/useReducer]
    E --> M[Configured Hooks]
    E --> N[Custom Patterns]

    F --> O[useReactTracer injection]
    F --> P[labelState calls]

Want to dive deeper? See Architecture Details for implementation specifics.

Usage

Basic Transformation

import { transform } from "@autotracer/inject-react18";

const sourceCode = `
  function MyComponent() {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    return <div>{count} {name}</div>;
  }
`;

const result = transform(sourceCode, {
  filename: "MyComponent.tsx",
  config: {
    mode: "opt-out",
    importSource: "@autotracer/react18",
    labelHooks: ["useState"],
  },
});

console.log(result.code);
// Output:
// import { useReactTracer } from '@autotracer/react18';
// function MyComponent() {
//   const __reactTracer = useReactTracer({ name: "MyComponent" });
//   const [count, setCount] = useState(0);
//   __reactTracer.labelState("count", 0);
//   const [name, setName] = useState('');
//   __reactTracer.labelState("name", 1);
//   return <div>{count} {name}</div>;
// }

Configuration Options

interface TransformConfig {
  /** Controls how components are selected for injection. */
  mode: "opt-in" | "opt-out";

  /** Include filters for files and components. */
  include?: {
    /** Glob patterns for files to include. */
    paths?: string[];

    /** Component name patterns to include (exact string, glob-like string, or RegExp). */
    components?: Array<string | RegExp>;
  };

  /** Exclude filters for files and components. */
  exclude?: {
    /** Glob patterns for files to exclude. */
    paths?: string[];

    /** Component name patterns to exclude (exact string, glob-like string, or RegExp). */
    components?: Array<string | RegExp>;
  };

  /** Enables React Server Components (RSC) safety checks. */
  serverComponents?: boolean;

  /** Module to import runtime helpers from when injecting. */
  importSource?: string;

  /** Specific hook names to label. */
  labelHooks?: string[];

  /** Regex pattern (as a string) for matching additional hook names. */
  labelHooksPattern?: string;
}

Pragma Control

Control tracing behavior for individual components using special leading comments:

function MyComponent() {
  const [state, setState] = useState();
  // ...
}

Notes:

  • Pragmas are always enabled; there is no configuration option to disable pragma handling.
  • @trace-disable always wins over @trace when both are present.
  • Class components are not instrumented by this transformer.

Class Components

This transformer injects hook-based tracing (useReactTracer) and therefore does not instrument React class components.

API Reference

transform(code, context)

The main transformation function.

Parameters:

  • code: string - Source code to transform
  • context: TransformContext - Transformation context with filename and config

Returns: TransformResult

  • code: string - Transformed source code
  • injected: boolean - Whether tracing was injected
  • components: ComponentInfo[] - Information about detected components

Hook Labeling Rules

  1. Built-in Hooks: useState and useReducer are always labeled
  2. Configured Hooks: Hooks listed in labelHooks are labeled
  3. Pattern Matching: Hooks matching labelHooksPattern regex are labeled

Component Detection

Automatically detects React components in various forms:

  • Function declarations: function MyComponent() {}
  • Arrow function expressions: const MyComponent = () => {}
  • Function expressions: const MyComponent = function() {}
  • HOC-wrapped components: memo(), forwardRef(), etc.

React Server Components (RSC)

If your app uses React Server Components (e.g., Next.js App Router), enable the RSC safety guard by setting serverComponents: true in the transform config (via the Vite plugin or direct usage). When enabled, a module is considered a Server Module unless it has a top-level directive:

"use client";

Only Client Components receive injections; Server Modules are returned unchanged. This avoids injecting client-only hooks into server code.

Key points:

  • Default is serverComponents: false to avoid surprising changes in non-RSC setups.
  • With serverComponents: true, normal mode/include/exclude/pragma rules apply only to files with the "use client" directive.
  • The check is conservative and literal: the directive must be exactly "use client" at the top level.

License

MIT