The DC-005 src/ refactor left depth-2 route files (routes/auth/*, routes/recipes/*, routes/apps/*, routes/arr/*, routes/config/*) with broken require() paths. A filesystem-resolving scanner found 67 broken requires across 21 files — three distinct bug classes: A) '../../../src/...' (3 levels up, above package root) — Bug 7, ~49 occurrences B) '../src/utils/...' (1 level up, resolves to nonexistent routes/src/) — ~15 occurrences C) routes/apps/restore.js:5 used utilities/responses (wrong dir) — should be utils/responses All fixed to '../../src/...' (or '../../src/utils/responses' for class C). routes/auth/totp.js was already fixed in the DC-006 commit. Post-fix: 922/922 tests pass, zero new ESLint warnings. No logic changes — purely mechanical require() path corrections.
77 lines
2.7 KiB
JavaScript
77 lines
2.7 KiB
JavaScript
const express = require('express');
|
|
const deployRoutes = require('./deploy');
|
|
const manageRoutes = require('./manage');
|
|
const { NotFoundError } = require('../../src/utilities/errors');
|
|
const { ok } = require('../../src/utils/responses');
|
|
|
|
/**
|
|
* Recipes routes aggregator
|
|
* @param {Object} ctx - Application context (for backward compatibility)
|
|
* @returns {express.Router}
|
|
*/
|
|
module.exports = function(ctx) {
|
|
const router = express.Router();
|
|
|
|
const deps = {
|
|
docker: ctx.docker,
|
|
credentialManager: ctx.credentialManager,
|
|
servicesStateManager: ctx.servicesStateManager,
|
|
asyncHandler: ctx.asyncHandler,
|
|
errorResponse: ctx.errorResponse,
|
|
log: ctx.log,
|
|
notification: ctx.notification,
|
|
buildDomain: ctx.buildDomain,
|
|
caddy: ctx.caddy,
|
|
addServiceToConfig: ctx.addServiceToConfig,
|
|
APP_TEMPLATES: ctx.APP_TEMPLATES,
|
|
siteConfig: ctx.siteConfig
|
|
};
|
|
|
|
// All recipe routes require premium license
|
|
router.use(ctx.licenseManager.requirePremium('recipes'));
|
|
|
|
// GET /api/recipes/templates — list all recipe templates
|
|
router.get('/templates', deps.asyncHandler(async (req, res) => {
|
|
const { RECIPE_TEMPLATES, RECIPE_CATEGORIES } = require('../../src/recipes/recipe-templates');
|
|
const templates = Object.entries(RECIPE_TEMPLATES).map(([id, recipe]) => ({
|
|
id,
|
|
name: recipe.name,
|
|
description: recipe.description,
|
|
icon: recipe.icon,
|
|
category: recipe.category,
|
|
type: 'recipe',
|
|
difficulty: recipe.difficulty,
|
|
popularity: recipe.popularity,
|
|
componentCount: recipe.components.length,
|
|
requiredCount: recipe.components.filter(c => c.required).length,
|
|
optionalCount: recipe.components.filter(c => !c.required).length,
|
|
components: recipe.components.map(c => ({
|
|
id: c.id,
|
|
role: c.role,
|
|
required: c.required,
|
|
internal: c.internal || false,
|
|
templateRef: c.templateRef || null,
|
|
note: c.note || null
|
|
})),
|
|
setupInstructions: recipe.setupInstructions
|
|
}));
|
|
|
|
ok(res, { templates, categories: RECIPE_CATEGORIES });
|
|
}, 'recipe-templates'));
|
|
|
|
// GET /api/recipes/templates/:recipeId — get single recipe template detail
|
|
router.get('/templates/:recipeId', deps.asyncHandler(async (req, res) => {
|
|
const { RECIPE_TEMPLATES } = require('../../src/recipes/recipe-templates');
|
|
const recipe = RECIPE_TEMPLATES[req.params.recipeId];
|
|
if (!recipe) throw new NotFoundError(`Recipe template ${req.params.recipeId}`);
|
|
|
|
ok(res, { recipe: { id: req.params.recipeId, ...recipe } });
|
|
}, 'recipe-template-detail'));
|
|
|
|
// Mount deploy and manage sub-routes — pass full ctx for sub-routes that reference ctx.*
|
|
router.use(deployRoutes(ctx));
|
|
router.use(manageRoutes(ctx));
|
|
|
|
return router;
|
|
};
|