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

refactor-check

v1.0.0

Published

Tool to validate PR changes conform to refactoring patterns

Readme

Refactor Check Tool

A tool to validate that PR changes conform to specified refactoring patterns, enabling safer automated code transformations.

Purpose

When performing automated refactorings (like adding type annotations across many files), you want to ensure that ONLY the intended changes were made. This tool:

  1. Checks that all changes in a PR match explicitly defined transformation patterns
  2. Flags files with non-conforming changes for manual review
  3. Makes PR review faster and more confident for large automated refactorings

Installation

npm install -g refactor-check

Or run directly with npx:

npx refactor-check <pr-number> [pattern-file]

Usage

refactor-check <pr-number> [pattern-file]

Examples:

# Use pattern from PR description (```refactor-check block)
refactor-check 1821

# Use local pattern file
refactor-check 1821 example-patterns/add-props-types.yaml

Pattern From PR Description

If you don't specify a pattern file, the tool will fetch the pattern from the PR description. Add a refactor-check code block to your PR description:

## Refactor Pattern

```refactor-check
allowed_patterns:
  - change: "Add type annotation"
    before: "function ${Name}({ ${Params} })"
    after: "function ${Name}({ ${Params} }: ${Type})"

excluded_files:
  - path/to/file.tsx
```

Pattern File Format

Pattern files are written in YAML and specify exactly what code transformations are allowed.

Basic Structure

name: "Refactoring Name"

allowed_patterns:
  - change: "Description of what this pattern does"
    before: "code pattern before"
    after: "code pattern after"

excluded_files:
  path/to/file.tsx: "Reason this file has other changes"

Pattern Syntax

Patterns use holes to match code transformations:

  • ${Name} - Matches any text that doesn't contain unbalanced delimiters ()[]{}
  • Holes with the same name must match the same text in before/after patterns
  • Holes can match inside strings: '${Path}/firebaseutil.js' matches '../util/firebaseutil.js'
  • Note: All patterns ignore whitespace differences by default, making them robust to code formatting changes.

Pattern Combination

The tool automatically combines "add" and "remove" patterns:

  • If you have a pattern that removes X (before: X, after: "")
  • And a pattern that adds Y (before: "", after: Y)
  • They automatically combine to match hunks that change X to Y

This means you don't need explicit "change" patterns - just define what can be added and removed.

Path-Agnostic Patterns

Use ${Path} to match any path prefix, making patterns work regardless of import style:

- change: "Remove import from firebaseutil (any path)"
  before: "import { ${Items} } from '${Path}/firebaseutil.js';"
  after: ""

This matches:

  • import { foo } from 'util/firebaseutil.js';
  • import { foo } from '../util/firebaseutil.js';
  • import { foo } from '../../util/firebaseutil.js';

Example Patterns

Changing Import Paths

- change: "Change import from one path to another"
  before: "import { ${Items} } from '${FromPath}';"
  after: "import { ${Items} } from '${ToPath}';"

This matches:

// Before
import { foo, bar } from '../util/firebaseutil.js';

// After
import { foo, bar } from '../util/keyutil.js';

The ${Items} must match exactly in before/after (same items imported).

Adding Generic Types to Hooks

- change: "Add generic type to hook"
  before: "${Hook}(${Args})"
  after: "${Hook}<${Type}>(${Args})"

This matches:

// Before
const [items, setItems] = useState([])

// After
const [items, setItems] = useState<string[]>([])

Adding Imports

- change: "Add import statement"
  before: ""
  after: "import { ${Items} } from '${Path}';"

This matches any new import being added.

Output

The tool will:

Pass - If all changes match the allowed patterns

✅ All changes conform to the allowed patterns!
✅ PR #1821 is ready for review.

Fail - If some files have non-conforming changes

❌ Found 3 file(s) with non-conforming changes:

  client/feature/topic/reading-list.tsx
    Contains changes not matching allowed patterns
    (2 hunk(s) don't match any pattern)

📝 Suggested additions to excluded_files:
  client/feature/topic/reading-list.tsx: "Contains changes not matching allowed patterns"

Excluded Files

Files listed in excluded_files are skipped during pattern checking. Use this for files that legitimately need other changes beyond the refactoring.

Exclusion Syntax

excluded_files:
  # Exclude specific file
  client/some/file.tsx: "Also fixes a bug in validation logic"

  # Exclude entire folder (note trailing /)
  server/adapter/: "New adapter implementation files"

  # Exclude pattern with wildcards
  **/*.test.ts: "Test files have additional changes"
  server/modules/*.ts: "All module files need review"

Supported patterns:

  • Exact path: path/to/file.ts - Matches only that specific file
  • Folder: path/to/folder/ - Matches all files in that folder (note trailing /)
  • Wildcards:
    • * matches any characters except / (single folder level)
    • ** matches any characters including / (multiple folder levels)
    • ? matches any single character

Examples:

  • server/adapter/ - Excludes server/adapter/auth/types.ts, server/adapter/database/firebase.ts, etc.
  • **/*.test.ts - Excludes all test files in any folder
  • server/modules/*.ts - Excludes all .ts files directly in server/modules/

How It Works

  1. Fetches PR diff using gh pr diff
  2. Parses hunks - each contiguous change in the diff
  3. Pattern matching - converts pattern templates to regex, matches against each hunk
  4. AST-aware - uses template variables to match code structure, not just text
  5. Reports - lists files with non-matching changes

Example: PR #1821

PR #1821 adds TypeScript prop types to React components. The pattern file specifies:

  • Adding type definitions
  • Adding type annotations to function parameters
  • Adding generic types to hooks
  • Adding imports for types

Result: 34/37 files matched the patterns perfectly. 3 files were flagged because they had additional changes (modifying existing type definitions), which correctly required manual review.

Tips

  • Start specific - Write patterns for the exact transformations you're making
  • Test on real PRs - Run the tool on your PR to see what doesn't match
  • Iterate patterns - Add patterns for legitimate variations you discover
  • Use excluded_files - For files that genuinely need other changes
  • Keep it simple - Patterns should be easy for humans to read and verify

Files

  • index.js - Main tool implementation
  • hole-matcher.js - Hole-based pattern matching engine
  • example-patterns/add-props-types.yaml - Example pattern file for adding React prop types
  • example-patterns/auth-adapter-refactor.yaml - Example pattern file for auth adapter refactoring
  • README.md - This file

Requirements

  • Node.js 20+
  • gh CLI (GitHub CLI) installed and authenticated
  • Access to the repository containing the PR

License

Apache-2.0