UNPKG

node-apis

Version:

🚀 Advanced TypeScript API generator with clean architecture, comprehensive testing, and automatic formatting. Generate production-ready Node.js APIs with complete integration test suites.

507 lines (444 loc) • 17.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateCrudControllerContent = exports.getCrudControllerFileNames = void 0; /** * Gets the list of CRUD controller file names for a module */ const naming_utils_1 = require("../shared/utils/naming.utils"); const getCrudControllerFileNames = ({ moduleName }) => { const naming = (0, naming_utils_1.getModuleNaming)(moduleName); return [ `create.${naming.file}.ts`, `get.${naming.file}.ts`, `list.${naming.file}.ts`, `delete.${naming.file}.ts`, `update.${naming.file}.ts`, ]; }; exports.getCrudControllerFileNames = getCrudControllerFileNames; const generateCrudControllerContent = ({ operation, moduleName, framework = 'express', }) => { const naming = (0, naming_utils_1.getModuleNaming)(moduleName); const capitalizedOperation = operation.charAt(0).toUpperCase() + operation.slice(1); switch (operation) { case 'create': return generateCreateControllerContent(naming, capitalizedOperation, framework); case 'get': return generateGetControllerContent(naming, capitalizedOperation, framework); case 'list': return generateListControllerContent(naming, capitalizedOperation, framework); case 'update': return generateUpdateControllerContent(naming, capitalizedOperation, framework); case 'delete': return generateDeleteControllerContent(naming, capitalizedOperation, framework); default: return generateGenericControllerContent(naming, capitalizedOperation, operation, framework); } }; exports.generateCrudControllerContent = generateCrudControllerContent; const generateCreateControllerContent = (naming, _capitalizedOperation, framework = 'express') => { if (framework === 'hono') { return `import type { Context } from 'hono'; import { validatePayload } from '../validators/create.${naming.file}'; import create${naming.class}Handler from '../handlers/create.${naming.file}'; export default async function create${naming.class}Controller(c: Context): Promise<Response> { try { const requestId = c.req.header('x-request-id') || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; const body = await c.req.json(); console.info(\`\${requestId} [CONTROLLER] - CREATE ${naming.constant} payload:\`, JSON.stringify(body, null, 2)); const validation = validatePayload(body); if (!validation.success) { return c.json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }, 400); } const result = await create${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 201; return c.json(result, statusCode); } catch (error) { return c.json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Failed to process request', statusCode: 500 } }, 500); } } `; } return `import type { Request, Response } from 'express'; import { validatePayload } from '../validators/create.${naming.file}'; import create${naming.class}Handler from '../handlers/create.${naming.file}'; export default async function create${naming.class}Controller(req: Request, res: Response): Promise<void> { const requestId = (req.headers['x-request-id'] as string) || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; console.info(\`\${requestId} [CONTROLLER] - CREATE ${naming.constant} payload:\`, JSON.stringify(req.body, null, 2)); const validation = validatePayload(req.body); if (!validation.success) { res.status(400).json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }); return; } const result = await create${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 201; res.status(statusCode).json(result); } `; }; /** * Generates GET controller content */ const generateGetControllerContent = (naming, _capitalizedOperation, framework = 'express') => { if (framework === 'hono') { return `import type { Context } from 'hono'; import { validatePayload } from '../validators/get.${naming.file}'; import get${naming.class}Handler from '../handlers/get.${naming.file}'; export default async function get${naming.class}Controller(c: Context): Promise<Response> { try { const requestId = c.req.header('x-request-id') || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; const id = c.req.param('id'); console.info(\`\${requestId} [CONTROLLER] - GET ${naming.constant} payload:\`, JSON.stringify({ id }, null, 2)); const validation = validatePayload({ id }); if (!validation.success) { return c.json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }, 400); } const result = await get${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; return c.json(result, statusCode); } catch (error) { return c.json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Failed to process request', statusCode: 500 } }, 500); } } `; } return `import type { Request, Response } from 'express'; import { validatePayload } from '../validators/get.${naming.file}'; import get${naming.class}Handler from '../handlers/get.${naming.file}'; export default async function get${naming.class}Controller(req: Request, res: Response): Promise<void> { const requestId = (req.headers['x-request-id'] as string) || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; console.info(\`\${requestId} [CONTROLLER] - GET ${naming.constant} payload:\`, JSON.stringify({ id: req.params.id }, null, 2)); const validation = validatePayload({ id: req.params.id }); if (!validation.success) { res.status(400).json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }); return; } const result = await get${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; res.status(statusCode).json(result); } `; }; /** * Generates LIST controller content */ const generateListControllerContent = (naming, _capitalizedOperation, framework = 'express') => { if (framework === 'hono') { return `import type { Context } from 'hono'; import { validatePayload } from '../validators/list.${naming.file}'; import list${naming.class}sHandler from '../handlers/list.${naming.file}'; export default async function list${naming.class}sController(c: Context): Promise<Response> { try { const requestId = c.req.header('x-request-id') || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; const query = c.req.query(); console.info(\`\${requestId} [CONTROLLER] - LIST ${naming.constant} payload:\`, JSON.stringify(query, null, 2)); const validation = validatePayload(query); if (!validation.success) { return c.json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }, 400); } const result = await list${naming.class}sHandler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; return c.json(result, statusCode); } catch (error) { return c.json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Failed to process request', statusCode: 500 } }, 500); } } `; } return `import type { Request, Response } from 'express'; import { validatePayload } from '../validators/list.${naming.file}'; import list${naming.class}sHandler from '../handlers/list.${naming.file}'; export default async function list${naming.class}sController(req: Request, res: Response): Promise<void> { const requestId = (req.headers['x-request-id'] as string) || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; console.info(\`\${requestId} [CONTROLLER] - LIST ${naming.constant} payload:\`, JSON.stringify(req.query, null, 2)); const validation = validatePayload(req.query); if (!validation.success) { res.status(400).json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }); return; } const result = await list${naming.class}sHandler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; res.status(statusCode).json(result); } `; }; /** * Generates UPDATE controller content */ const generateUpdateControllerContent = (naming, _capitalizedOperation, framework = 'express') => { if (framework === 'hono') { return `import type { Context } from 'hono'; import { validatePayload } from '../validators/update.${naming.file}'; import update${naming.class}Handler from '../handlers/update.${naming.file}'; export default async function update${naming.class}Controller(c: Context): Promise<Response> { try { const requestId = c.req.header('x-request-id') || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; const id = c.req.param('id'); const body = await c.req.json(); const payload = { id, ...body }; console.info(\`\${requestId} [CONTROLLER] - UPDATE ${naming.constant} payload:\`, JSON.stringify(payload, null, 2)); const validation = validatePayload(payload); if (!validation.success) { return c.json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }, 400); } const result = await update${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; return c.json(result, statusCode); } catch (error) { return c.json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Failed to process request', statusCode: 500 } }, 500); } } `; } return `import type { Request, Response } from 'express'; import { validatePayload } from '../validators/update.${naming.file}'; import update${naming.class}Handler from '../handlers/update.${naming.file}'; export default async function update${naming.class}Controller(req: Request, res: Response): Promise<void> { const requestId = (req.headers['x-request-id'] as string) || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; console.info(\`\${requestId} [CONTROLLER] - UPDATE ${naming.constant} payload:\`, JSON.stringify({ id: req.params.id, ...req.body }, null, 2)); const validation = validatePayload({ id: req.params.id, ...req.body }); if (!validation.success) { res.status(400).json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }); return; } const result = await update${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; res.status(statusCode).json(result); } `; }; /** * Generates DELETE controller content */ const generateDeleteControllerContent = (naming, _capitalizedOperation, framework = 'express') => { if (framework === 'hono') { return `import type { Context } from 'hono'; import { validatePayload } from '../validators/delete.${naming.file}'; import delete${naming.class}Handler from '../handlers/delete.${naming.file}'; export default async function delete${naming.class}Controller(c: Context): Promise<Response> { try { const requestId = c.req.header('x-request-id') || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; const id = c.req.param('id'); const body = await c.req.json().catch(() => ({})); // DELETE might not have body const payload = { id, ...body }; console.info(\`\${requestId} [CONTROLLER] - DELETE ${naming.constant} payload:\`, JSON.stringify(payload, null, 2)); const validation = validatePayload(payload); if (!validation.success) { return c.json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }, 400); } const result = await delete${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; return c.json(result, statusCode); } catch (error) { return c.json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Failed to process request', statusCode: 500 } }, 500); } } `; } return `import type { Request, Response } from 'express'; import { validatePayload } from '../validators/delete.${naming.file}'; import delete${naming.class}Handler from '../handlers/delete.${naming.file}'; export default async function delete${naming.class}Controller(req: Request, res: Response): Promise<void> { const requestId = (req.headers['x-request-id'] as string) || \`req-\${Date.now()}-\${Math.random().toString(36).substr(2, 9)}\`; console.info(\`\${requestId} [CONTROLLER] - DELETE ${naming.constant} payload:\`, JSON.stringify({ id: req.params.id, ...req.body }, null, 2)); const validation = validatePayload({ id: req.params.id, ...req.body }); if (!validation.success) { res.status(400).json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400 } }); return; } const result = await delete${naming.class}Handler({ ...validation.data, requestId }); const statusCode = result.error ? result.error.statusCode : 200; res.status(statusCode).json(result); } `; }; /** * Generates generic controller content (fallback) */ const generateGenericControllerContent = (naming, _capitalizedOperation, operation, framework = 'express') => { if (framework === 'hono') { return `import type { Context } from 'hono'; import { typeResult } from '../types/${operation}.${naming.file}'; import { validatePayload } from '../validators/${operation}.${naming.file}'; import { randomBytes } from 'crypto'; import ${operation}${naming.class}Handler from '../handlers/${operation}.${naming.file}'; export const ${operation}${naming.class} = async (c: Context): Promise<Response> => { const requestId = randomBytes(16).toString('hex'); try { const body = await c.req.json(); const validation = validatePayload(body); if (!validation.success) { return c.json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400, requestId } }, 400); } const payload = validation.data; // Call handler with requestId const result = await ${operation}${naming.class}Handler({ ...payload, requestId }); const statusCode = result.error ? result.error.statusCode || 500 : 200; return c.json(result, statusCode); } catch (error) { return c.json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Something went wrong', statusCode: 500, requestId } }, 500); } }; `; } return `import type { Request, Response } from 'express'; import { typeResult } from '../types/${operation}.${naming.file}'; import { validatePayload } from '../validators/${operation}.${naming.file}'; import { randomBytes } from 'crypto'; import ${operation}${naming.class}Handler from '../handlers/${operation}.${naming.file}'; export const ${operation}${naming.class} = async (req: Request, res: Response): Promise<void> => { const requestId = randomBytes(16).toString('hex'); try { const validation = validatePayload(req.body); if (!validation.success) { res.status(400).json({ data: null, error: { code: 'VALIDATION_ERROR', message: validation.error.message, statusCode: 400, requestId } }); return; } const payload = validation.data; // Call handler with requestId const result = await ${operation}${naming.class}Handler({ ...payload, requestId }); const statusCode = result.error ? result.error.statusCode || 500 : 200; res.status(statusCode).json(result); } catch (error) { res.status(500).json({ data: null, error: { code: 'INTERNAL_ERROR', message: 'Something went wrong', statusCode: 500, requestId } }); } }; `; }; //# sourceMappingURL=crud.controllers.js.map