irving-frias/drupal-watcher
Composer 安装命令:
composer require irving-frias/drupal-watcher
包简介
Drupal file watcher — monitors custom modules/themes and auto-runs drush cr. Supports DDEV, Lando, and local environments.
README 文档
README
🚀 A smart file watcher for Drupal that monitors your custom modules and themes, automatically running
drush crwhen changes are detected.
Table of Contents
- What it does
- Features
- Requirements
- Installation
- Usage
- Configuration
- Architecture
- Examples
- Troubleshooting
- FAQ
- Development
- Contributing
- License
Quick Start
# 1. Install in your Drupal project composer require irving-frias/drupal-watcher # 2. Start watching (local/Lando) vendor/bin/drupal-watcher start # Or with DDEV ddev drupal-watcher start # 3. Edit a file — drush cr runs automatically! 📝 my-module.module 🔄 Clearing cache... ✔ Cache cleared in 2.3s
What it does
Forget running drush cr manually every time you edit a file. Drupal Watcher:
- Watches your custom module and theme files in real time
- Auto-detects changes in
.html.twig,.inc,.yml,.module,.theme,.php,.info.yml, and.services.ymlfiles - Runs
drush crintelligently with debounce to avoid saturating your system - Compatible with DDEV, Lando, and local environments (use
ddev drupal-watcherin DDEV) - Persists your custom routes in a configuration file
Features
Route management
- Add, remove, list, and reset watched routes on the fly
- Filter with
--watch=<path>and--no-watch=<path>at startup - Persistence in
watcher.config.json - Existence validation for watched folders
Drupal-optimized
- Auto-detects Drupal docroot (
docroot,web,html,public,drupal) - Smart debounce (800ms default)
- DDEV-ready: run
ddev drupal-watcher <command>
Blazing fast
- Bun-powered installation (10-30× faster than npm)
- Cold start in ~8ms
- Low memory footprint
Built with Bun
- Modular JavaScript architecture (
src/) - Zero external dependencies (Bun only)
- Compilable to standalone binary
- Singleton PID file prevents duplicate watchers
- Real-time stats on stop
Requirements
- Bun (installed globally:
curl -fsSL https://bun.sh/install | bash) - Composer (PHP dependency manager)
- Drupal with Drush installed
Installation
From Packagist (recommended)
composer require irving-frias/drupal-watcher
From local repository
- Clone or download the package to
packages/drupal-watcher/ - Add the repository to your
composer.json:
"repositories": [ { "type": "path", "url": "packages/drupal-watcher" } ]
- Install:
composer require irving-frias/drupal-watcher:@dev
From ZIP
- Download the latest ZIP
- Extract to
packages/drupal-watcher/ - Follow steps from local repository method
Usage
All commands run from your Drupal project root.
Start the watcher
# Local or Lando vendor/bin/drupal-watcher start # DDEV ddev drupal-watcher start
Example output:
🚀 Starting Drupal Watcher
📁 Drupal root: docroot
🔧 Drush: drush cr
👀 Watching routes:
- docroot/modules/custom
- docroot/themes/custom
✔ Watcher active. Waiting for changes... (Ctrl+C to stop)
List configured routes
vendor/bin/drupal-watcher list
Shows current routes, patterns, debounce, and drush command.
Add a route
vendor/bin/drupal-watcher add docroot/modules/contrib
Remove a route
vendor/bin/drupal-watcher remove docroot/modules/contrib
Reset routes to defaults
vendor/bin/drupal-watcher reset
Check watcher status
vendor/bin/drupal-watcher status
Shows PID and uptime if running.
Filter routes at startup
# Watch only a specific route (substring match) vendor/bin/drupal-watcher start --watch=modules/my-module # Exclude a specific route (substring match) vendor/bin/drupal-watcher start --no-watch=modules/contrib # Abort if Drush is not responding vendor/bin/drupal-watcher start --abort-on-drush-error # Dry run — preview what would happen without starting vendor/bin/drupal-watcher start --dry-run
Global flags
| Flag | Description |
|---|---|
--version, -V |
Show version number |
--no-colors |
Disable colored output (useful for CI/logs) |
--verbose, -v |
Show full Drush stdout/stderr output |
Runtime features
- Timestamps: Every change and cache clear is prefixed with
[HH:MM:SS] - Pending counter: Shows how many unique files are queued in the current debounce window, e.g.
📝 file.php (3 pending) - Cache clear duration: Shows how long
drush crtook, e.g.✔ Cache cleared in 2.3s - Post-clear feedback: Each post-clear command shows success/failure and duration
- Shutdown stats: On Ctrl+C, shows uptime, total changes, unique files, and cache clears
- SIGTERM handling: Also responds to
SIGTERMfor clean Docker/process manager shutdowns - Reset confirmation:
vendor/bin/drupal-watcher resetasks for confirmation before removing custom routes
Composer script aliases (optional)
Add to your root composer.json:
"scripts": { "watcher:start": "vendor/bin/drupal-watcher start", "watcher:list": "vendor/bin/drupal-watcher list", "watcher:status": "vendor/bin/drupal-watcher status", "watcher:add": "vendor/bin/drupal-watcher add", "watcher:remove": "vendor/bin/drupal-watcher remove", "watcher:reset": "vendor/bin/drupal-watcher reset" }
Run with: composer watcher:start
Configuration
The watcher.config.json file is auto-created in your project root.
File structure
{
"routes": [
"docroot/modules/custom",
"docroot/themes/custom"
],
"patterns": [
".html.twig", ".inc", ".yml", ".module",
".theme", ".php", ".info.yml", ".services.yml"
],
"excludePatterns": [],
"debounce": 800,
"drushCmd": null,
"drushCommand": "cr",
"drushArgs": [],
"postClearCommands": []
}
Options
| Option | Description | Default |
|---|---|---|
routes |
Paths to watch | ["docroot/modules/custom", "docroot/themes/custom"] |
patterns |
File extensions to watch | [".html.twig", ".inc", ".yml", ".module", ".theme", ".php", ".info.yml", ".services.yml"] |
excludePatterns |
Extensions to ignore (e.g. [".css", ".js"]) |
[] |
debounce |
Wait time (ms) before running drush | 800 |
drushCmd |
Custom Drush command | null (auto-detects) |
drushCommand |
Drush subcommand to run | "cr" |
drushArgs |
Extra arguments for Drush | [] |
postClearCommands |
Shell commands to run after each cache clear | [] |
Notes
- Patterns: Add or remove extensions as needed.
.phpis included by default since Drupal modules contain PHP hooks, forms, and controllers. - Exclude patterns: Ignore files like
.cssor.jsto avoid unnecessary cache clears. - Debounce: Increase for large projects (e.g.
1200for 1.2s). - Custom Drush: Set
drushCmdto a specific binary path if needed. In DDEV, runddev drupal-watcherinstead. - drushCommand: Use
"cc bin"for faster partial cache clears instead of full"cr". - postClearCommands: Array of shell commands run after each cache clear (e.g.
["drush cex"]).
Architecture
bin/drupal-watcher # Thin entry point (shebang + import main)
src/
main.js # Argument parsing and dispatch
config.js # Config load/save, Drupal root detection, PID management
commands.js # All CLI commands (start, list, status, add, remove, reset, help)
drush.js # Drush resolution, health check, execution
watcher.js # File watching, debounce, PID enforcement, stats
utils.js # Color constants, Drupal paths, helpers
test/
config.test.ts # Unit tests (21 tests, see below)
Key design decisions
rootparameter: Every function accepts an optionalrootfor testability (defaults toprocess.cwd())- Per-root cache:
_rootCacheMap caches detection results; useinvalidateConfigCache(root)to reset - PID singleton:
.drupal-watcher.pidprevents multiple watcher instances - No TypeScript: Pure JS avoids a build step for the Composer distribution
- import with
.jsextension: ESM requires explicit file extensions
Examples
Example 1: Basic watcher
# Install composer require irving-frias/drupal-watcher # Start (local or Lando) vendor/bin/drupal-watcher start # In DDEV ddev drupal-watcher start # Edit a .twig file... 📝 my-template.html.twig 🔄 Clearing cache... ✔ Cache cleared.
Example 2: Add contrib modules
vendor/bin/drupal-watcher add docroot/modules/contrib vendor/bin/drupal-watcher list
Example 3: Faster cache clear
Edit watcher.config.json:
{
"drushCommand": "cc bin"
}
Runs drush cc bin instead of the full drush cr.
Example 4: Post-clear commands
Automatically run drush cex after each change:
{
"postClearCommands": ["drush cex"]
}
Example 5: Standalone binary
# From Composer package bun build --compile ./vendor/irving-frias/drupal-watcher/bin/drupal-watcher --outfile ./drupal-watcher # Or from local repo bun run build # current platform bun run build:mac # macOS ARM64 bun run build:linux # Linux x64 bun run build:win # Windows x64 ./drupal-watcher start
Example 6: Run tests
bun test # run once bun run test:watch # watch mode
Example 7: Advanced start flags
vendor/bin/drupal-watcher start --abort-on-drush-error vendor/bin/drupal-watcher start --watch=docroot/modules/custom/my-module vendor/bin/drupal-watcher start --no-watch=docroot/modules/contrib vendor/bin/drupal-watcher start --dry-run vendor/bin/drupal-watcher start --no-colors vendor/bin/drupal-watcher start --verbose
Example 8: Display version
vendor/bin/drupal-watcher --version
# → drupal-watcher v0.3.0
vendor/bin/drupal-watcher -V
Troubleshooting
❌ command not found: bun
Bun is not installed globally.
- Check installation:
bun --version - Install:
curl -fsSL https://bun.sh/install | bash
❌ Drush not found
The watcher looks for Drush at:
vendor/bin/drush(Drupal project)bin/drush(alternative)
Verify that:
- Drush is installed:
composer require drush/drush - You are running from the Drupal project root
- In DDEV, use
ddev drupal-watcher <command>instead ofvendor/bin/drupal-watcher <command>
❌ None of the configured routes exist
Ensure that:
docroot/modules/customanddocroot/themes/customexist- Or add valid routes with
vendor/bin/drupal-watcher add
❌ Watcher does not detect changes
Verify that:
- You are editing files with correct extensions (
.html.twig,.inc,.yml,.module,.theme,.php,.info.yml,.services.yml) - Files are inside configured routes
- On large projects, the watcher may take time to initialize
❌ Cache is cleared too frequently
Increase debounce in watcher.config.json:
{
"debounce": 1200
}
FAQ
Why Bun instead of Node.js?
Bun is 10-30× faster for installs and 8× faster for cold starts. It's an all-in-one runtime, package manager, and bundler, reducing dependencies and complexity.
Can I use it without Composer?
Yes. Compile to a standalone binary:
bun build --compile ./bin/drupal-watcher --outfile ./drupal-watcher ./drupal-watcher start
Does it work on Windows?
Yes. Bun is cross-platform. Install from bun.sh.
Can I watch multiple projects?
Not directly. Each project has its own watcher and configuration. Run from each project's root.
What files does it watch?
Default patterns: .html.twig, .inc, .yml, .module, .theme, .php, .info.yml, .services.yml. Add more in watcher.config.json.
Development
Setup
git clone <repo> cd drupal-watcher bun install
Testing
bun test # 21 tests bun run test:watch # watch mode
Building
bun run build # current platform bun run build:linux # Linux x64 bun run build:mac # macOS ARM64 bun run build:win # Windows x64
Auto-tagging
The repository includes a GitHub Action (.github/workflows/tag.yml) that automatically creates a new tag on push to main. It analyzes commits since the last tag:
| Commit type | Bump |
|---|---|
BREAKING CHANGE or feat!:... |
major |
feat:... |
minor |
fix:, refactor:, chore:, ci:, docs:, etc |
patch |
Commands reference
| Command | Description |
|---|---|
start |
Start the file watcher |
stop (Ctrl+C / SIGTERM) |
Stop the watcher (prints stats) |
status |
Show PID and uptime if running |
list |
Display current configuration |
add <path> |
Add a route to watch |
remove <path> |
Remove a watched route |
reset |
Reset routes to defaults (with confirmation) |
help [command] |
Show detailed help |
Flags reference
| Flag | Applies to | Description |
|---|---|---|
--abort-on-drush-error |
start |
Exit if Drush health check fails |
--watch=<path> |
start |
Filter routes to those containing <path> (substring) |
--no-watch=<path> |
start |
Exclude routes containing <path> (substring) |
--dry-run |
start |
Preview configuration without starting the watcher |
--verbose, -v |
start |
Show full Drush output |
--no-colors |
all | Disable ANSI colors |
--version, -V |
all | Show version number |
--help, -h |
all | Show help |
Contributing
Contributions are welcome!
- Fork the project
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Reporting issues
Use the issue tracker for bugs or feature requests.
License
MIT. See LICENSE.
Acknowledgments
Built with ❤️ by Irving Frías
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-23