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
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ For cleanup-specific findings:
npx fallow dead-code
```

116 framework plugins. No Node.js runtime required for static analysis. No config needed for the first run.
117 framework plugins. No Node.js runtime required for static analysis. No config needed for the first run.

## What is Fallow?

Expand Down Expand Up @@ -749,14 +749,15 @@ See the [full configuration reference](https://docs.fallow.tools/configuration/o

## Framework plugins

116 built-in plugins detect entry points, convention exports, config-defined aliases, and template-visible usage for your framework automatically.
117 built-in plugins detect entry points, convention exports, config-defined aliases, and template-visible usage for your framework automatically.

| Category | Plugins |
|---|---|
| **Frameworks** | Next.js, Nuxt, Remix, Qwik, SvelteKit, Gatsby, Astro, Angular, NestJS, AdonisJS, Contentlayer, Fumadocs, Lit, Obsidian, Ember, Expo, Expo Router, Electron, and more |
| **Bundlers** | Vite, Webpack, Rspack, Rsbuild, Rollup, Rolldown, Tsup, Tsdown, pkg-utils, Parcel |
| **Testing** | Vitest, Jest, Playwright, Cypress, Storybook, Stryker, Mocha, Ava, tap, tsd |
| **CI/CD & Release** | Danger, Commitlint, Commitizen, Semantic Release |
| **Deployment** | Vercel, Wrangler, Sentry, OpenNext Cloudflare |
| **CSS** | Tailwind, PostCSS, UnoCSS, PandaCSS |
| **Databases & Backend** | Prisma, Drizzle, Knex, TypeORM, Kysely, Convex |
| **Blockchain** | Hardhat |
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,7 @@ mod typescript;
mod unocss;
mod varlock;
mod velite;
mod vercel;
mod vite;
mod vitepress;
mod vitest;
Expand Down
8 changes: 5 additions & 3 deletions crates/core/src/plugins/registry/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ use super::super::{
tailwind::TailwindPlugin, tanstack_router::TanstackRouterPlugin, tap::TapPlugin,
tsd::TsdPlugin, tsdown::TsdownPlugin, tsup::TsupPlugin, turborepo::TurborepoPlugin,
typedoc::TypedocPlugin, typeorm::TypeormPlugin, typescript::TypeScriptPlugin,
unocss::UnoCssPlugin, varlock::VarlockPlugin, velite::VelitePlugin, vite::VitePlugin,
vitepress::VitePressPlugin, vitest::VitestPlugin, webdriverio::WebdriverioPlugin,
webpack::WebpackPlugin, wrangler::WranglerPlugin, wuchale::WuchalePlugin, wxt::WxtPlugin,
unocss::UnoCssPlugin, varlock::VarlockPlugin, velite::VelitePlugin, vercel::VercelPlugin,
vite::VitePlugin, vitepress::VitePressPlugin, vitest::VitestPlugin,
webdriverio::WebdriverioPlugin, webpack::WebpackPlugin, wrangler::WranglerPlugin,
wuchale::WuchalePlugin, wxt::WxtPlugin,
};

/// Create all built-in plugin instances, categorized by domain.
Expand Down Expand Up @@ -145,6 +146,7 @@ pub fn create_builtin_plugins() -> Vec<Box<dyn Plugin>> {
// Blockchain
Box::new(HardhatPlugin),
// Deployment
Box::new(VercelPlugin),
Box::new(WranglerPlugin),
Box::new(OpenNextCloudflarePlugin),
Box::new(SentryPlugin),
Expand Down
20 changes: 20 additions & 0 deletions crates/core/src/plugins/vercel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! Vercel plugin.

use super::{Plugin, PluginResult};

const ENABLERS: &[&str] = &["vercel", "@vercel/config"];

const CONFIG_PATTERNS: &[&str] = &["vercel.{ts,js,mjs,cjs,mts}"];

const ALWAYS_USED: &[&str] = &["vercel.{ts,js,mjs,cjs,mts}"];

const TOOLING_DEPENDENCIES: &[&str] = &["vercel", "@vercel/config"];

define_plugin! {
struct VercelPlugin => "vercel",
enablers: ENABLERS,
config_patterns: CONFIG_PATTERNS,
always_used: ALWAYS_USED,
tooling_dependencies: TOOLING_DEPENDENCIES,
resolve_config: imports_only,
}
2 changes: 2 additions & 0 deletions crates/core/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ mod issue_635_scaffold_template_assets;
mod issue_638_node_script_entrypoints;
#[path = "integration_test/issue_754_eslint_meta_preset.rs"]
mod issue_754_eslint_meta_preset;
#[path = "integration_test/issue_820_vercel_ts_config.rs"]
mod issue_820_vercel_ts_config;
#[path = "integration_test/lexical_nodes.rs"]
mod lexical_nodes;
#[path = "integration_test/script_multiplexers.rs"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//! Issue #820: Vercel programmatic config files are convention entrypoints.

use super::common::{create_config, fixture_path};

fn unused_file_paths(
root: &std::path::Path,
results: &fallow_types::results::AnalysisResults,
) -> Vec<String> {
results
.unused_files
.iter()
.map(|finding| {
finding
.file
.path
.strip_prefix(root)
.unwrap_or(&finding.file.path)
.to_string_lossy()
.replace('\\', "/")
})
.collect()
}

#[test]
fn vercel_ts_config_is_not_reported_as_unused() {
let root = fixture_path("issue-820-vercel-ts-config");
let config = create_config(root.clone());
let results = fallow_core::analyze(&config).expect("analysis should succeed");

let unused_paths = unused_file_paths(&root, &results);
assert!(
!unused_paths.contains(&"vercel.ts".to_string()),
"vercel.ts is loaded by Vercel convention and must be credited, got {unused_paths:?}"
);
assert!(
unused_paths.contains(&"src/orphan.ts".to_string()),
"ordinary unused file should still be reported, got {unused_paths:?}"
);
}
10 changes: 10 additions & 0 deletions tests/fixtures/issue-820-vercel-ts-config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "issue-820-vercel-ts-config",
"version": "1.0.0",
"type": "module",
"main": "src/index.ts",
"devDependencies": {
"@vercel/config": "latest",
"vercel": "latest"
}
}
3 changes: 3 additions & 0 deletions tests/fixtures/issue-820-vercel-ts-config/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const greeting = "hello";

console.log(greeting);
1 change: 1 addition & 0 deletions tests/fixtures/issue-820-vercel-ts-config/src/orphan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const orphan = "unused";
6 changes: 6 additions & 0 deletions tests/fixtures/issue-820-vercel-ts-config/vercel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { VercelConfig } from "@vercel/config/v1";

export const config = {
regions: ["dub1"],
fluid: true,
} satisfies VercelConfig;
Loading