9.4 KiB
DashCaddy API Dependencies Map
Generated: 2026-03-22
Purpose: Document current ctx (context object) usage across routes to guide refactoring
Overview
The DashCaddy API currently uses a god object pattern where a single ctx (context) object is passed to all route modules. This object contains 50+ properties mixing:
- Utilities (asyncHandler, errorResponse, log)
- Domain objects (docker, caddy, dns, session)
- Managers (credentialManager, authManager, healthChecker)
- Configuration (SERVICES_FILE, CONFIG_FILE, siteConfig)
- Template data (APP_TEMPLATES, RECIPE_TEMPLATES)
Problem: Routes don't declare what they actually need — dependencies are hidden, making testing and refactoring difficult.
Goal: Move to explicit dependency injection where each route declares exactly what it needs.
Most-Used Properties (Refactor Priority)
| Property | Routes Using It | Type | Notes |
|---|---|---|---|
ctx.asyncHandler |
35 | Utility | Wrap async route handlers, universal dependency |
ctx.errorResponse |
27 | Utility | Standard error formatting |
ctx.log |
20 | Utility | Logger instance |
ctx.docker |
15 | Domain | Dockerode wrapper + helpers |
ctx.caddy |
12 | Domain | Caddyfile manipulation + reload |
ctx.fetchT |
12 | Utility | Timeout-wrapped fetch |
ctx.servicesStateManager |
12 | Manager | services.json state management |
ctx.credentialManager |
12 | Manager | Encrypted credential storage |
ctx.siteConfig |
10 | Config | Site-wide configuration |
ctx.buildDomain |
9 | Utility | Domain construction helper |
ctx.dns |
9 | Domain | DNS API wrapper |
Route Dependencies (By Route File)
High-Complexity Routes (10+ dependencies)
apps/deploy.js (15 dependencies)
// Current
module.exports = (ctx) => { ... };
// After refactor (explicit deps)
module.exports = ({
APP_TEMPLATES,
addServiceToConfig,
asyncHandler,
buildDomain,
buildServiceUrl,
caddy,
dns,
docker,
errorResponse,
log,
logError,
notification,
portLockManager,
safeErrorMessage,
siteConfig,
}) => { ... };
Refactor Priority: HIGH (core deployment logic, frequently used)
config/backup.js (16 dependencies)
// Dependencies
CONFIG_FILE, NOTIFICATIONS_FILE, SERVICES_FILE, TAILSCALE_CONFIG_FILE,
TOTP_CONFIG_FILE, asyncHandler, caddy, credentialManager, dns, errorResponse,
fetchT, loadDnsCredentials, loadNotificationConfig, loadSiteConfig, log, totpConfig
Refactor Priority: MEDIUM (backup/restore is critical but less frequent)
Opportunity: Extract backup logic to service layer
services.js (13 dependencies)
// Dependencies
SERVICES_FILE, asyncHandler, buildDomain, buildServiceUrl, caddy,
credentialManager, dns, errorResponse, log, resyncHealthChecker,
safeErrorMessage, servicesStateManager, siteConfig
Refactor Priority: HIGH (core service management, most-used route)
Medium-Complexity Routes (6-9 dependencies)
apps/restore.js(9 deps)auth/sso-gate.js(10 deps)dns.js(8 deps)health.js(8 deps)recipes/manage.js(8 deps)sites.js(12 deps)tailscale.js(9 deps)
Low-Complexity Routes (1-5 dependencies)
Good candidates for early refactoring (simpler, less risky):
backups.js(2 deps: asyncHandler, backupManager)containers.js(3 deps: asyncHandler, docker, log)credentials.js(3 deps: asyncHandler, credentialManager, errorResponse)license.js(3 deps: asyncHandler, errorResponse, licenseManager)monitoring.js(3 deps: asyncHandler, docker, resourceMonitor)notifications.js(3 deps: asyncHandler, errorResponse, notification)
Domain Object Breakdown
ctx.docker (used by 15 routes)
Properties/Methods:
find()— find container by namegetUsedPorts()— list ports in usesecurity— docker-security module
Routes:
- apps/deploy.js, apps/helpers.js, apps/removal.js, apps/restore.js, apps/templates.js
- arr/config.js, arr/detect.js, arr/helpers.js
- browse.js, containers.js, context.js, logs.js, monitoring.js
- recipes/deploy.js, recipes/manage.js
Refactor Suggestion: Extract to standalone service (services/docker-service.js)
ctx.caddy (used by 12 routes)
Properties/Methods:
modify()— modify Caddyfileread()— read Caddyfilereload()— reload CaddygenerateConfig()— generate route configverifySite()— test site accessibilityadminUrl,filePath— config properties
Routes:
- apps/deploy.js, apps/helpers.js, apps/removal.js, apps/restore.js, apps/templates.js
- config/backup.js, context.js
- recipes/deploy.js, recipes/manage.js
- services.js, sites.js, tailscale.js
Refactor Suggestion: Extract to services/caddy-service.js
ctx.dns (used by 9 routes)
Properties/Methods:
call()— DNS API callbuildUrl()— construct DNS API URLrequireToken()— token validationensureToken()— auto-refresh token if neededcreateRecord()— create DNS recordgetToken(),setToken()— token managementrefresh()— force token refresh
Routes:
- apps/deploy.js, apps/removal.js, apps/restore.js, apps/templates.js
- config/backup.js, context.js, dns.js
- services.js, sites.js
Refactor Suggestion: Extract to services/dns-service.js
Utility Functions (Universal Dependencies)
ctx.asyncHandler (35 routes)
What it does: Wraps async Express route handlers to catch errors
Current pattern:
router.get('/endpoint', ctx.asyncHandler(async (req, res) => {
// ... async logic
}));
Refactor suggestion: Keep as utility, but import directly instead of via ctx
const { asyncHandler } = require('../utils/async-handler');
router.get('/endpoint', asyncHandler(async (req, res) => {
// ... async logic
}));
ctx.log (20 routes)
What it does: Structured logger (log.info, log.error, log.warn)
Refactor suggestion: Import logger utility directly
const log = require('../utils/logger');
ctx.errorResponse (27 routes)
What it does: Standard error response formatting
Refactor suggestion: Utility function, import directly
const { errorResponse } = require('../utils/responses');
Manager Objects
ctx.credentialManager (12 routes)
What it does: AES-256-GCM encrypted credential storage
Routes using it:
- arr/credentials.js, arr/detect.js, arr/helpers.js
- auth/sso-gate.js, auth/totp.js
- config/backup.js, credentials.js, dns.js
- services.js, tailscale.js
Refactor suggestion: Keep as manager, inject explicitly
ctx.servicesStateManager (12 routes)
What it does: Thread-safe services.json state management
Refactor suggestion: Keep as manager, inject explicitly
ctx.healthChecker (1 route: health.js)
Refactor suggestion: Already well-isolated, just make explicit
Configuration Objects
ctx.siteConfig (10 routes)
What it does: Site-wide configuration (domain, TLS, etc.)
Refactor suggestion: Load once at app startup, inject where needed
File path constants (used by 6 routes)
SERVICES_FILE(6 routes)CONFIG_FILE(3 routes)TOTP_CONFIG_FILE(1 route)NOTIFICATIONS_FILE(1 route)ERROR_LOG_FILE(1 route)
Refactor suggestion: Move to src/config/paths.js, import directly
Refactoring Strategy
Phase 1: Low-Risk Routes (Start Here)
Refactor simple routes with 1-5 dependencies:
backups.js(2 deps)containers.js(3 deps)credentials.js(3 deps)license.js(3 deps)monitoring.js(3 deps)
Why: Low complexity, easier to verify correctness, builds confidence
Phase 2: Extract Common Utilities
Extract universal dependencies to standalone modules:
utils/async-handler.js(used by 35 routes)utils/responses.js(errorResponse, ok, etc.)utils/logger.js(structured logging)utils/http.js(fetchT wrapper)
Why: Reduces ctx bloat, makes imports explicit
Phase 3: Extract Domain Services
Convert domain objects to services:
services/docker-service.js(15 routes)services/caddy-service.js(12 routes)services/dns-service.js(9 routes)
Why: Separate business logic from HTTP handlers, testable in isolation
Phase 4: High-Complexity Routes
Refactor routes with 10+ dependencies:
services.js(13 deps) — most-used routeapps/deploy.js(15 deps) — core deploymentconfig/backup.js(16 deps) — extract backup servicesites.js(12 deps)
Why: Highest impact on maintainability
Success Metrics
Before Refactor
- God object
ctxwith 50+ properties - Hidden dependencies (routes don't declare what they use)
- Difficult to mock for testing (need entire ctx object)
After Refactor
- ✅ Routes declare explicit dependencies
- ✅ Utilities imported directly (no ctx indirection)
- ✅ Domain logic extracted to services
- ✅ Easy to mock (inject only what's needed)
- ✅ Self-documenting (route signature shows dependencies)
Next Steps
- ✅ Document current dependencies (this file)
- Refactor Phase 1 routes (low-risk, 1-5 deps)
- Extract utilities (asyncHandler, errorResponse, log)
- Extract domain services (docker, caddy, dns)
- Refactor high-complexity routes
- Remove
ctxgod object entirely
Generated by analyzing route files for ctx.* usage patterns.