From 039d3d07e2be2f1e118d1040b609d2b02939ebbc Mon Sep 17 00:00:00 2001 From: Krystie Date: Sun, 22 Mar 2026 11:01:40 +0100 Subject: [PATCH] Phase 1: Add dependency analysis documentation --- dashcaddy-api/DEPENDENCIES.md | 344 ++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 dashcaddy-api/DEPENDENCIES.md diff --git a/dashcaddy-api/DEPENDENCIES.md b/dashcaddy-api/DEPENDENCIES.md new file mode 100644 index 0000000..18c08a3 --- /dev/null +++ b/dashcaddy-api/DEPENDENCIES.md @@ -0,0 +1,344 @@ +# 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) +```javascript +// 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) +```javascript +// 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) +```javascript +// 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:** +```javascript +router.get('/endpoint', ctx.asyncHandler(async (req, res) => { + // ... async logic +})); +``` + +**Refactor suggestion:** Keep as utility, but import directly instead of via ctx +```javascript +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 +```javascript +const log = require('../utils/logger'); +``` + +--- + +### `ctx.errorResponse` (27 routes) +**What it does:** Standard error response formatting + +**Refactor suggestion:** Utility function, import directly +```javascript +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.*