diff --git a/dashcaddy-api/.eslintignore b/dashcaddy-api/.eslintignore new file mode 100644 index 0000000..3063216 --- /dev/null +++ b/dashcaddy-api/.eslintignore @@ -0,0 +1,5 @@ +node_modules/ +coverage/ +dist/ +build/ +*.min.js diff --git a/dashcaddy-api/.eslintrc.js b/dashcaddy-api/.eslintrc.js new file mode 100644 index 0000000..0f0b03a --- /dev/null +++ b/dashcaddy-api/.eslintrc.js @@ -0,0 +1,57 @@ +module.exports = { + env: { + node: true, + es2021: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'commonjs', + }, + rules: { + // Error Prevention + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + 'no-console': 'off', // We use structured logging, but console is okay for debug + 'no-undef': 'error', + 'no-unreachable': 'error', + 'no-constant-condition': ['error', { checkLoops: false }], + + // Code Quality + 'prefer-const': 'warn', + 'no-var': 'warn', + 'eqeqeq': ['warn', 'always', { null: 'ignore' }], + 'curly': ['warn', 'multi-line'], + 'no-throw-literal': 'error', + + // Async/Await + 'require-await': 'warn', + 'no-async-promise-executor': 'error', + 'no-await-in-loop': 'off', // Sometimes intentional for sequential operations + + // Style (Prettier handles formatting, these are semantic) + 'consistent-return': 'off', // Express routes don't always return + 'no-nested-ternary': 'warn', + 'max-depth': ['warn', 4], + 'complexity': ['warn', 20], + + // Prevent common pitfalls + 'no-eval': 'error', + 'no-implied-eval': 'error', + 'no-new-func': 'error', + 'no-with': 'error', + 'no-proto': 'error', + }, + overrides: [ + { + // Test files can be more lenient + files: ['**/__tests__/**/*.js', '**/*.test.js', '**/*.spec.js'], + env: { + jest: true, + }, + rules: { + 'no-unused-expressions': 'off', + 'max-depth': 'off', + }, + }, + ], +}; diff --git a/dashcaddy-api/.prettierignore b/dashcaddy-api/.prettierignore new file mode 100644 index 0000000..8d806ca --- /dev/null +++ b/dashcaddy-api/.prettierignore @@ -0,0 +1,6 @@ +node_modules/ +coverage/ +dist/ +build/ +package-lock.json +*.min.js diff --git a/dashcaddy-api/.prettierrc b/dashcaddy-api/.prettierrc new file mode 100644 index 0000000..1e1e4fc --- /dev/null +++ b/dashcaddy-api/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 120, + "tabWidth": 2, + "useTabs": false, + "arrowParens": "avoid", + "endOfLine": "lf" +} diff --git a/dashcaddy-api/package-lock.json b/dashcaddy-api/package-lock.json index b8943c5..d7431c5 100644 --- a/dashcaddy-api/package-lock.json +++ b/dashcaddy-api/package-lock.json @@ -1,12 +1,12 @@ { "name": "dashcaddy-api", - "version": "1.1.0", + "version": "1.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dashcaddy-api", - "version": "1.1.0", + "version": "1.1.5", "dependencies": { "compression": "^1.8.1", "cors": "^2.8.6", diff --git a/dashcaddy-api/routes/apps/deploy.js b/dashcaddy-api/routes/apps/deploy.js index 2e457cb..c76eee8 100644 --- a/dashcaddy-api/routes/apps/deploy.js +++ b/dashcaddy-api/routes/apps/deploy.js @@ -7,6 +7,7 @@ const { isValidPort } = require('../../input-validator'); const { exists } = require('../../fs-helpers'); const platformPaths = require('../../platform-paths'); const { ValidationError } = require('../errors'); +const { logError } = require('../../src/utils/logging'); /** * Apps deployment routes factory * @param {Object} deps - Explicit dependencies @@ -22,8 +23,20 @@ const { ValidationError } = require('../errors'); * @returns {express.Router} */ -module.exports = function({ docker, caddy, credentialManager, servicesStateManager, portLockManager, asyncHandler, errorResponse, log, helpers }) { +module.exports = function({ docker, caddy, credentialManager, servicesStateManager, portLockManager, asyncHandler, errorResponse, log, helpers, APP_TEMPLATES, siteConfig, buildDomain, buildServiceUrl, addServiceToConfig, dns, notification, safeErrorMessage }) { const router = express.Router(); + + // Ctx shim for backward compatibility with existing route code + const ctx = { + APP_TEMPLATES, + siteConfig, + buildDomain, + buildServiceUrl, + addServiceToConfig, + dns, + notification, + safeErrorMessage + }; async function deployDashCAStaticSite(template, userConfig) { const destPath = platformPaths.caCertDir; @@ -260,6 +273,9 @@ module.exports = function({ docker, caddy, credentialManager, servicesStateManag let containerId; let usedExisting = false; + + // Process template variables for manifest (only needed for Docker containers) + const processedTemplate = template.isStaticSite ? null : helpers.processTemplateVariables(template, config); if (template.isStaticSite) { log.info('deploy', 'Deploying static site', { appId }); diff --git a/dashcaddy-api/routes/apps/index.js b/dashcaddy-api/routes/apps/index.js index a14798e..3c4128c 100644 --- a/dashcaddy-api/routes/apps/index.js +++ b/dashcaddy-api/routes/apps/index.js @@ -23,7 +23,16 @@ module.exports = function(ctx) { portLockManager: ctx.portLockManager, asyncHandler: ctx.asyncHandler, errorResponse: ctx.errorResponse, - log: ctx.log + log: ctx.log, + // Additional context properties needed by routes + APP_TEMPLATES: ctx.APP_TEMPLATES, + siteConfig: ctx.siteConfig, + buildDomain: ctx.buildDomain, + buildServiceUrl: ctx.buildServiceUrl, + addServiceToConfig: ctx.addServiceToConfig, + dns: ctx.dns, + notification: ctx.notification, + safeErrorMessage: ctx.safeErrorMessage }; // Initialize helpers with dependencies diff --git a/dashcaddy-api/routes/arr/config.js b/dashcaddy-api/routes/arr/config.js index a949e1b..ff4409e 100644 --- a/dashcaddy-api/routes/arr/config.js +++ b/dashcaddy-api/routes/arr/config.js @@ -2,6 +2,7 @@ const express = require('express'); const { APP_PORTS, ARR_SERVICES } = require('../../constants'); const { validateURL, validateToken } = require('../../input-validator'); const { ValidationError, AuthenticationError, NotFoundError } = require('../errors'); +const { logError } = require('../../src/utils/logging'); /** * Arr configuration routes factory @@ -16,8 +17,14 @@ const { ValidationError, AuthenticationError, NotFoundError } = require('../erro * @param {Object} deps.helpers - Arr helpers module * @returns {express.Router} */ -module.exports = function({ credentialManager, servicesStateManager, docker, fetchT, asyncHandler, errorResponse, log, helpers }) { +module.exports = function({ credentialManager, servicesStateManager, docker, fetchT, asyncHandler, errorResponse, log, helpers, notification, safeErrorMessage }) { const router = express.Router(); + + // Ctx shim for backward compatibility + const ctx = { + notification, + safeErrorMessage + }; // Auto-configure Overseerr with detected services router.post('/arr/configure-overseerr', asyncHandler(async (req, res) => { diff --git a/dashcaddy-api/routes/arr/index.js b/dashcaddy-api/routes/arr/index.js index 49a4a66..58d6ba7 100644 --- a/dashcaddy-api/routes/arr/index.js +++ b/dashcaddy-api/routes/arr/index.js @@ -17,7 +17,10 @@ module.exports = function(ctx) { fetchT: ctx.fetchT, asyncHandler: ctx.asyncHandler, errorResponse: ctx.errorResponse, - log: ctx.log + log: ctx.log, + // Additional context properties needed by arr routes + notification: ctx.notification, + safeErrorMessage: ctx.safeErrorMessage }; // Initialize helpers with dependencies