Files
dashcaddy/dashcaddy-api/DEPENDENCIES.md
2026-03-22 11:01:40 +01:00

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 name
  • getUsedPorts() — list ports in use
  • security — 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 Caddyfile
  • read() — read Caddyfile
  • reload() — reload Caddy
  • generateConfig() — generate route config
  • verifySite() — test site accessibility
  • adminUrl, 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 call
  • buildUrl() — construct DNS API URL
  • requireToken() — token validation
  • ensureToken() — auto-refresh token if needed
  • createRecord() — create DNS record
  • getToken(), setToken() — token management
  • refresh() — 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:

  1. backups.js (2 deps)
  2. containers.js (3 deps)
  3. credentials.js (3 deps)
  4. license.js (3 deps)
  5. monitoring.js (3 deps)

Why: Low complexity, easier to verify correctness, builds confidence


Phase 2: Extract Common Utilities

Extract universal dependencies to standalone modules:

  1. utils/async-handler.js (used by 35 routes)
  2. utils/responses.js (errorResponse, ok, etc.)
  3. utils/logger.js (structured logging)
  4. utils/http.js (fetchT wrapper)

Why: Reduces ctx bloat, makes imports explicit


Phase 3: Extract Domain Services

Convert domain objects to services:

  1. services/docker-service.js (15 routes)
  2. services/caddy-service.js (12 routes)
  3. 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:

  1. services.js (13 deps) — most-used route
  2. apps/deploy.js (15 deps) — core deployment
  3. config/backup.js (16 deps) — extract backup service
  4. sites.js (12 deps)

Why: Highest impact on maintainability


Success Metrics

Before Refactor

  • God object ctx with 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

  1. Document current dependencies (this file)
  2. Refactor Phase 1 routes (low-risk, 1-5 deps)
  3. Extract utilities (asyncHandler, errorResponse, log)
  4. Extract domain services (docker, caddy, dns)
  5. Refactor high-complexity routes
  6. Remove ctx god object entirely

Generated by analyzing route files for ctx.* usage patterns.