UNPKG

ultimate-crud

Version:

Ultimate dynamic CRUD API generator with REST, GraphQL, OpenAPI support and association handling for Node.js/Express/Sequelize

109 lines (101 loc) 4.97 kB
/** * REST utilities for Ultimate CRUD * * @license MIT * @copyright 2025 cnos-dev * @author Harish Kashyap (CNOS Dev) */ // utils/rest.js const { defineModelFromTable } = require('./dynamicModel'); const { createCrudRouter, createGetRouter } = require('./dynamicRouter'); const { handleDatabaseError, asyncErrorHandler } = require('./errorHandler'); async function setupRest(app, sequelize, entities) { for (const entity of entities) { if (entity.type === "table") { const model = await defineModelFromTable(sequelize, entity.name, entity.schema, entity.associations || []); const pkAttr = Object.keys(model.rawAttributes).find(attr => model.rawAttributes[attr].primaryKey); app.get(`${entity.route}/:${pkAttr}`, asyncErrorHandler(async (req, res, next) => { try { const item = await model.findByPk(req.params[pkAttr]); if (item) res.status(200).json({ message: entity.responseMessages?.[200] || "Success", data: item }); else next({ status: 404, message: entity.responseMessages?.[404] || "Not found" }); } catch (err) { const mappedError = handleDatabaseError(err, 'read', entity.name); const message = entity.responseMessages?.[mappedError.status] || mappedError.message; res.status(mappedError.status).json({ error: message, details: mappedError.details }); } })); app.put(`${entity.route}/:${pkAttr}`, asyncErrorHandler(async (req, res, next) => { try { const item = await model.findByPk(req.params[pkAttr]); if (!item) return res.status(404).json({ error: entity.responseMessages?.[404] || "Not found" }); await item.update(req.body); res.status(200).json({ message: entity.responseMessages?.[200] || "Success", data: item }); } catch (err) { const mappedError = handleDatabaseError(err, 'update', entity.name); const message = entity.responseMessages?.[mappedError.status] || mappedError.message; res.status(mappedError.status).json({ error: message, details: mappedError.details }); } })); app.delete(`${entity.route}/:${pkAttr}`, asyncErrorHandler(async (req, res, next) => { try { const item = await model.findByPk(req.params[pkAttr]); if (!item) return res.status(404).json({ error: entity.responseMessages?.[404] || "Not found" }); await item.destroy(); res.status(200).json({ message: entity.responseMessages?.[200] || "Deleted" }); } catch (err) { const mappedError = handleDatabaseError(err, 'delete', entity.name); const message = entity.responseMessages?.[mappedError.status] || mappedError.message; res.status(mappedError.status).json({ error: message, details: mappedError.details }); } })); app.use(entity.route, createCrudRouter(model, { responseMessages: entity.responseMessages })); } else if (entity.type === "view") { const model = await defineModelFromTable(sequelize, entity.name, entity.schema, entity.associations || []); app.use(entity.route, createGetRouter(model, { responseMessages: entity.responseMessages })); } else if (entity.type === "query") { app.get(entity.route, asyncErrorHandler(async (req, res, next) => { try { const [results] = await sequelize.query(entity.sql); const msg = entity.responseMessages?.[200] || "Success"; res.status(200).json({ message: msg, data: results }); } catch (err) { const mappedError = handleDatabaseError(err, 'read', entity.name); const msg = entity.responseMessages?.[mappedError.status] || mappedError.message; res.status(mappedError.status).json({ error: msg, details: mappedError.details }); } })); } else if (entity.type === "procedure") { app.post(entity.route, asyncErrorHandler(async (req, res, next) => { try { const params = req.body ? Object.values(req.body) : []; const placeholders = params.map(() => '?').join(','); const sql = `CALL ${entity.procedure}(${placeholders})`; const results = await sequelize.query(sql, { replacements: params }); const msg = entity.responseMessages?.[200] || "Procedure executed successfully"; res.status(200).json({ message: msg, data: results }); } catch (err) { const mappedError = handleDatabaseError(err, 'create', entity.name); const msg = entity.responseMessages?.[mappedError.status] || mappedError.message; res.status(mappedError.status).json({ error: msg, details: mappedError.details }); } })); } } } module.exports = { setupRest };