UNPKG

@bodheesh/create-bodhi-node-app

Version:

Create a production-ready Node.js REST API with zero configuration

239 lines (201 loc) 5.88 kB
const fs = require('fs').promises; const path = require('path'); async function generateFirebaseAPI(schema, outputDir, type) { if (type === 'rest') { await generateRESTAPI(schema, outputDir); } else if (type === 'graphql') { await generateGraphQLAPI(schema, outputDir); } } async function generateRESTAPI(schema, outputDir) { // Generate model const modelContent = generateModelContent(schema); await fs.writeFile( path.join(outputDir, `${schema.name}.model.js`), modelContent ); // Generate controller const controllerContent = generateControllerContent(schema); await fs.writeFile( path.join(outputDir, `${schema.name}.controller.js`), controllerContent ); // Generate routes const routesContent = generateRoutesContent(schema); await fs.writeFile( path.join(outputDir, `${schema.name}.routes.js`), routesContent ); // Generate Firebase security rules const rulesContent = generateSecurityRules(schema); await fs.writeFile( path.join(outputDir, 'firestore.rules'), rulesContent ); } function generateModelContent(schema) { return ` const admin = require('firebase-admin'); const db = admin.firestore(); const collection = db.collection('${schema.name.toLowerCase()}s'); class ${schema.name} { constructor(data) { ${Object.keys(schema.fields).map(field => `this.${field} = data.${field};` ).join('\n ')} this.createdAt = data.createdAt || new Date(); this.updatedAt = data.updatedAt || new Date(); } static async create(data) { const doc = await collection.add({ ...data, createdAt: new Date(), updatedAt: new Date() }); return { id: doc.id, ...data }; } static async findAll(options = {}) { const { limit = 10, page = 1, orderBy = 'createdAt', orderDir = 'desc' } = options; const offset = (page - 1) * limit; let query = collection.orderBy(orderBy, orderDir); const snapshot = await query.get(); const total = snapshot.size; query = query.limit(limit).offset(offset); const docs = await query.get(); return { items: docs.docs.map(doc => ({ id: doc.id, ...doc.data() })), total, totalPages: Math.ceil(total / limit), currentPage: page }; } static async findById(id) { const doc = await collection.doc(id).get(); if (!doc.exists) return null; return { id: doc.id, ...doc.data() }; } static async update(id, data) { const ref = collection.doc(id); const doc = await ref.get(); if (!doc.exists) return null; await ref.update({ ...data, updatedAt: new Date() }); const updated = await ref.get(); return { id: updated.id, ...updated.data() }; } static async delete(id) { const ref = collection.doc(id); const doc = await ref.get(); if (!doc.exists) return false; await ref.delete(); return true; } } module.exports = ${schema.name}; `; } function generateControllerContent(schema) { return ` const ${schema.name} = require('./${schema.name}.model'); // Create exports.create = async (req, res) => { try { const new${schema.name} = await ${schema.name}.create(req.body); res.status(201).json(new${schema.name}); } catch (error) { res.status(400).json({ message: error.message }); } }; // Read all exports.findAll = async (req, res) => { try { const { page = 1, limit = 10, orderBy, orderDir } = req.query; const items = await ${schema.name}.findAll({ page: parseInt(page), limit: parseInt(limit), orderBy, orderDir }); res.json(items); } catch (error) { res.status(500).json({ message: error.message }); } }; // Read one exports.findOne = async (req, res) => { try { const item = await ${schema.name}.findById(req.params.id); if (!item) { return res.status(404).json({ message: 'Item not found' }); } res.json(item); } catch (error) { res.status(500).json({ message: error.message }); } }; // Update exports.update = async (req, res) => { try { const updated${schema.name} = await ${schema.name}.update(req.params.id, req.body); if (!updated${schema.name}) { return res.status(404).json({ message: 'Item not found' }); } res.json(updated${schema.name}); } catch (error) { res.status(400).json({ message: error.message }); } }; // Delete exports.delete = async (req, res) => { try { const deleted = await ${schema.name}.delete(req.params.id); if (!deleted) { return res.status(404).json({ message: 'Item not found' }); } res.json({ message: 'Item deleted successfully' }); } catch (error) { res.status(500).json({ message: error.message }); } }; `; } function generateRoutesContent(schema) { return ` const express = require('express'); const router = express.Router(); const ${schema.name}Controller = require('./${schema.name}.controller'); // Create router.post('/', ${schema.name}Controller.create); // Read all router.get('/', ${schema.name}Controller.findAll); // Read one router.get('/:id', ${schema.name}Controller.findOne); // Update router.put('/:id', ${schema.name}Controller.update); // Delete router.delete('/:id', ${schema.name}Controller.delete); module.exports = router; `; } function generateSecurityRules(schema) { return ` rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /${schema.name.toLowerCase()}s/{document=**} { allow read: if true; allow create: if request.auth != null; allow update: if request.auth != null && request.auth.uid == resource.data.userId; allow delete: if request.auth != null && request.auth.uid == resource.data.userId; } } } `; } module.exports = { generateFirebaseAPI };