Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Framework Filters

Detect and filter repositories by the frameworks they use, going beyond simple dependency checks.

Overview

FrameworkFilter identifies frameworks through multiple signals:

  • Configuration files (e.g., next.config.js, angular.json)
  • Dependency patterns (combinations of packages)
  • Project structure (directories, file patterns)
  • Import patterns in source code

Supported Frameworks

JavaScript/TypeScript

FrameworkDetection Method
Reactreact dependency + JSX files
Next.jsnext.config.* + next dependency
Vuevue dependency + .vue files
Nuxtnuxt.config.* + nuxt dependency
Angularangular.json + @angular/core
Sveltesvelte.config.* + svelte dependency
Expressexpress + server patterns
NestJS@nestjs/core + decorators
Gatsbygatsby-config.* + gatsby
Remixremix.config.* + @remix-run/*

Python

FrameworkDetection Method
Djangodjango + manage.py + settings.py
Flaskflask + app.py patterns
FastAPIfastapi + async patterns
Pyramidpyramid dependency
Tornadotornado dependency

Ruby

FrameworkDetection Method
Railsrails gem + config/application.rb
Sinatrasinatra gem + app patterns
Hanamihanami gem

Java

FrameworkDetection Method
Spring Bootspring-boot-* + @SpringBootApplication
Springspring-* dependencies
Quarkusquarkus-* + application.properties
Micronautmicronaut-*
Jakarta EEjakarta.* dependencies

Go

FrameworkDetection Method
Gingithub.com/gin-gonic/gin
Echogithub.com/labstack/echo
Fibergithub.com/gofiber/fiber
Chigithub.com/go-chi/chi

Rust

FrameworkDetection Method
Actixactix-web crate
Axumaxum crate
Rocketrocket crate
Warpwarp crate

C#

FrameworkDetection Method
ASP.NET CoreMicrosoft.AspNetCore.*
BlazorMicrosoft.AspNetCore.Components.*
WPFPresentationFramework reference
WinFormsSystem.Windows.Forms reference

Basic Usage

#![allow(unused)]
fn main() {
use refactor::prelude::*;

// Find all Next.js projects
Codemod::from_github_org("company", token)
    .repositories(|r| r
        .uses_framework(Framework::NextJs))
    .apply(transform)
    .execute()?;
}

Framework Enum

#![allow(unused)]
fn main() {
pub enum Framework {
    // JavaScript/TypeScript
    React,
    NextJs,
    Vue,
    Nuxt,
    Angular,
    Svelte,
    Express,
    NestJS,
    Gatsby,
    Remix,

    // Python
    Django,
    Flask,
    FastAPI,

    // Ruby
    Rails,
    Sinatra,

    // Java
    Spring,
    SpringBoot,
    Quarkus,

    // Go
    Gin,
    Echo,
    Fiber,

    // Rust
    Actix,
    Axum,
    Rocket,

    // C#
    AspNetCore,
    Blazor,
}
}

Multiple Frameworks

All Required (AND)

#![allow(unused)]
fn main() {
.repositories(|r| r
    .uses_framework(Framework::React)
    .uses_framework(Framework::Express))  // Full-stack React + Express
}

Any Required (OR)

#![allow(unused)]
fn main() {
// Find repos using any React meta-framework
.repositories(|r| r
    .uses_any_framework(&[
        Framework::NextJs,
        Framework::Gatsby,
        Framework::Remix,
    ]))
}

Framework Detection Details

Next.js Detection

#![allow(unused)]
fn main() {
// Detected by:
// 1. next.config.js or next.config.mjs exists
// 2. package.json has "next" dependency
// 3. pages/ or app/ directory structure
// 4. Imports from "next/*"

.uses_framework(Framework::NextJs)
}

Rails Detection

#![allow(unused)]
fn main() {
// Detected by:
// 1. Gemfile contains "rails"
// 2. config/application.rb exists
// 3. app/controllers/ structure
// 4. config/routes.rb exists

.uses_framework(Framework::Rails)
}

Spring Boot Detection

#![allow(unused)]
fn main() {
// Detected by:
// 1. spring-boot-starter-* dependencies
// 2. @SpringBootApplication annotation
// 3. application.properties or application.yml
// 4. pom.xml with spring-boot-starter-parent

.uses_framework(Framework::SpringBoot)
}

Custom Framework Detection

Define custom framework detection rules:

#![allow(unused)]
fn main() {
use refactor::discovery::FrameworkFilter;

let custom_framework = FrameworkFilter::custom("my-framework")
    .requires_dependency("my-framework-core", "*")
    .requires_file("my-framework.config.js")
    .requires_pattern("src/**/*.myfw");

.repositories(|r| r
    .framework(custom_framework))
}

Direct Usage

#![allow(unused)]
fn main() {
use refactor::discovery::FrameworkFilter;

let filter = FrameworkFilter::new(Framework::React);

// Check a single repository
if filter.matches(Path::new("./my-project"))? {
    println!("Project uses React");
}

// Get detailed info
if let Some(info) = filter.detect(Path::new("./my-project"))? {
    println!("Framework: {}", info.name);
    println!("Version: {:?}", info.version);
    println!("Confidence: {:.0}%", info.confidence * 100.0);
}
}

Confidence Scores

Detection returns confidence scores:

#![allow(unused)]
fn main() {
let result = FrameworkFilter::new(Framework::React)
    .detect(Path::new("./project"))?;

match result {
    Some(detection) if detection.confidence > 0.9 => {
        println!("Definitely React");
    }
    Some(detection) if detection.confidence > 0.5 => {
        println!("Probably React ({}%)", detection.confidence * 100.0);
    }
    Some(_) => {
        println!("Might be React, low confidence");
    }
    None => {
        println!("Not React");
    }
}
}

Framework Version Detection

#![allow(unused)]
fn main() {
let detection = FrameworkFilter::new(Framework::NextJs)
    .detect(Path::new("./project"))?;

if let Some(d) = detection {
    if let Some(version) = d.version {
        if version.major >= 13 {
            println!("Uses App Router (Next.js 13+)");
        } else {
            println!("Uses Pages Router");
        }
    }
}
}

Use Cases

Framework Migration

#![allow(unused)]
fn main() {
// Find Create React App projects to migrate to Next.js
Codemod::from_github_org("company", token)
    .repositories(|r| r
        .uses_framework(Framework::React)
        .has_dependency("react-scripts", "*")
        .missing_framework(Framework::NextJs))
    .collect_repos()?;
}

Framework Inventory

#![allow(unused)]
fn main() {
// Count framework usage across organization
let repos = Codemod::from_github_org("company", token)
    .collect_all_repos()?;

let mut framework_counts = HashMap::new();
for repo in &repos {
    for framework in Framework::all() {
        if FrameworkFilter::new(framework).matches(&repo.path)? {
            *framework_counts.entry(framework).or_insert(0) += 1;
        }
    }
}
}

Framework-Specific Transforms

#![allow(unused)]
fn main() {
Codemod::from_github_org("company", token)
    .repositories(|r| r.uses_framework(Framework::Express))
    .apply(|ctx| {
        // Apply Express-specific security patches
        ctx.add_middleware("helmet")
    })
    .execute()?;
}

Error Handling

#![allow(unused)]
fn main() {
use refactor::error::RefactorError;

let filter = FrameworkFilter::new(Framework::React);

match filter.matches(Path::new("./project")) {
    Ok(true) => println!("Uses React"),
    Ok(false) => println!("Doesn't use React"),
    Err(RefactorError::IoError(e)) => {
        println!("Failed to read project: {}", e);
    }
    Err(e) => return Err(e.into()),
}
}

See Also