UNPKG

4bnode

Version:

4bnode is a CLI-powered backend development platform with a built-in visual dashboard to generate, manage, and test Node.js/Express APIs faster.

117 lines (97 loc) 3.15 kB
#!/usr/bin/env node import path from "path"; import { select } from "@inquirer/prompts"; import { toPascalCase } from "./lib/names.js"; import { listRoutes, listModels, getModelSchema } from "./lib/project.js"; import { getRouteFilePath, addImportToRoute, insertCodeIntoRoute, detectHttpMethod, getRequestDataSource, } from "./lib/routeFile.js"; import { showHeader, showTaskDone, showError, showFileAction, installDeps, } from "./lib/ui.js"; async function main() { showHeader("add-mongo-update", "Add data update route"); const routeFiles = listRoutes(); if (routeFiles.length === 0) { showError("No route files found in src/routes."); process.exit(1); } const modelFiles = listModels(); if (modelFiles.length === 0) { showError("No model files found in src/models."); process.exit(1); } const selectedRoute = await select({ message: "Select route file to modify:", choices: routeFiles.map((f) => ({ name: f, value: f })), }); const selectedModelFile = await select({ message: "Select model file to use:", choices: modelFiles.map((f) => ({ name: f, value: f })), }); const modelName = path.basename(selectedModelFile, ".js"); const pascalName = toPascalCase(modelName); const fields = getModelSchema(modelName); if (fields.length === 0) { showError("No fields found in the selected model."); process.exit(1); } console.log(); const routeFilePath = getRouteFilePath(selectedRoute); const method = detectHttpMethod(routeFilePath); const dataSource = getRequestDataSource(method); let importBlock = `import ${pascalName} from '../models/${modelName}.js';`; let passwordLogic = ""; if (fields.includes("password")) { importBlock = `import bcrypt from 'bcrypt';\n${importBlock}`; passwordLogic = ` if (updatedData.password) { const salt = await bcrypt.genSalt(10); updatedData.password = await bcrypt.hash(updatedData.password, salt); }`; } addImportToRoute(routeFilePath, importBlock); const fieldAssignments = fields .map((f) => ` ${f}: ${dataSource}.${f}`) .join(",\n"); const updateCode = ` router.put('/:id', async (req, res) => { const updatedData = { ${fieldAssignments} }; ${passwordLogic} try { const updatedDocument = await ${pascalName}.findByIdAndUpdate(req.params.id, updatedData, { returnDocument: 'after' }); if (!updatedDocument) { return res.status(404).json({ message: 'Document not found' }); } res.json({ message: 'Data updated successfully', data: updatedDocument }); } catch (err) { console.error(err); res.status(500).json({ message: 'Server error' }); } });`; insertCodeIntoRoute(routeFilePath, updateCode); showFileAction("updated", `src/routes/${selectedRoute}`); if (fields.includes("password")) { await installDeps("bcrypt"); } showTaskDone("Update route added", [ `Route: PUT /:id in ${selectedRoute}`, `Model: ${modelName}`, `Fields: ${fields.join(", ")}`, ]); } main().catch((err) => { if (err.name === "ExitPromptError") process.exit(0); showError(err.message); process.exit(1); });