Skip to content

Commit

Permalink
completed server side implementation (mongodb)
Browse files Browse the repository at this point in the history
  • Loading branch information
ksmooi committed Oct 28, 2024
1 parent 4a51c41 commit f111aa3
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/apps/mongodb_app/server/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import logger from './logger';

dotenv.config();

// Enable Mongoose debugging
mongoose.set('debug', true);

const connectDB = async () => {
try {
//await mongoose.connect('mongodb://blogUser:securePassword123@localhost:27017/blogDB?authSource=admin');
const uri = process.env.MONGODB_URI || 'mongodb://localhost:27017/blogDB';
await mongoose.connect(uri);
logger.info('MongoDB Connected');
} catch (error: any) {
logger.error('MongoDB connection error: %s', error.message);
process.exit(1);
}
};

export default connectDB;
8 changes: 8 additions & 0 deletions src/apps/mongodb_app/server/errorHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Request, Response, NextFunction } from 'express';

const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
console.error('Unhandled Error:', err.stack);
res.status(500).json({ message: 'An unexpected error occurred.', error: err.message });
};

export default errorHandler;
29 changes: 29 additions & 0 deletions src/apps/mongodb_app/server/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createLogger, format, transports } from 'winston';

const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
format.errors({ stack: true }),
format.splat(),
format.json()
),
defaultMeta: { service: 'blog-service' },
transports: [
new transports.File({ filename: 'error.log', level: 'error' }),
new transports.File({ filename: 'combined.log' }),
],
});

// If we're not in production then **ALSO** log to the `console` with the colorized simple format.
if (process.env.NODE_ENV !== 'production') {
logger.add(
new transports.Console({
format: format.combine(format.colorize(), format.simple()),
})
);
}

export default logger;
22 changes: 22 additions & 0 deletions src/apps/mongodb_app/server/post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Schema, model, Document } from 'mongoose';

export interface IPost extends Document {
title: string;
content: string;
author: string;
createdAt: Date;
updatedAt: Date;
}

const postSchema = new Schema<IPost>(
{
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: String, required: true },
},
{ timestamps: true }
);

const Post = model<IPost>('Post', postSchema);

export default Post;
68 changes: 68 additions & 0 deletions src/apps/mongodb_app/server/postController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Request, Response } from 'express';
import postService from './postService';
import logger from './logger';

class PostController {
public async createPost(req: Request, res: Response): Promise<void> {
try {
const post = await postService.createPost(req.body);
res.status(201).json(post);
} catch (error: any) {
// Log the actual error for server-side debugging
logger.error('Error creating post:', error.message);

// Send a more detailed error message to the client
res.status(500).json({ message: 'Error creating post', error: error.message });
}
}

public async getAllPosts(req: Request, res: Response): Promise<void> {
try {
const posts = await postService.getAllPosts();
res.status(200).json(posts);
} catch (error) {
res.status(500).json({ message: 'Error fetching posts', error });
}
}

public async getPostById(req: Request, res: Response): Promise<void> {
try {
const post = await postService.getPostById(req.params.id);
if (post) {
res.status(200).json(post);
} else {
res.status(404).json({ message: 'Post not found' });
}
} catch (error) {
res.status(500).json({ message: 'Error fetching post', error });
}
}

public async updatePost(req: Request, res: Response): Promise<void> {
try {
const post = await postService.updatePost(req.params.id, req.body);
if (post) {
res.status(200).json(post);
} else {
res.status(404).json({ message: 'Post not found' });
}
} catch (error) {
res.status(500).json({ message: 'Error updating post', error });
}
}

public async deletePost(req: Request, res: Response): Promise<void> {
try {
const post = await postService.deletePost(req.params.id);
if (post) {
res.status(200).json({ message: 'Post deleted successfully' });
} else {
res.status(404).json({ message: 'Post not found' });
}
} catch (error) {
res.status(500).json({ message: 'Error deleting post', error });
}
}
}

export default new PostController();
12 changes: 12 additions & 0 deletions src/apps/mongodb_app/server/postRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Router } from 'express';
import postController from './postController';

const router = Router();

router.post('/', postController.createPost);
router.get('/', postController.getAllPosts);
router.get('/:id', postController.getPostById);
router.put('/:id', postController.updatePost);
router.delete('/:id', postController.deletePost);

export default router;
26 changes: 26 additions & 0 deletions src/apps/mongodb_app/server/postService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Post, { IPost } from './post';

class PostService {
public async createPost(data: Partial<IPost>): Promise<IPost> {
const post = new Post(data);
return await post.save();
}

public async getAllPosts(): Promise<IPost[]> {
return await Post.find();
}

public async getPostById(id: string): Promise<IPost | null> {
return await Post.findById(id);
}

public async updatePost(id: string, data: Partial<IPost>): Promise<IPost | null> {
return await Post.findByIdAndUpdate(id, data, { new: true });
}

public async deletePost(id: string): Promise<IPost | null> {
return await Post.findByIdAndDelete(id);
}
}

export default new PostService();
32 changes: 32 additions & 0 deletions src/apps/mongodb_app/server/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// npx ts-node src/apps/mongodb_app/server/server.ts

// create file `APP_HOME/.env`
// MONGODB_URI=mongodb://blogUser:securePassword123@localhost:27017/blogDB?authSource=admin
// MONGODB_APP_SERVER_PORT=5000

import express from 'express';
import connectDB from './db';
import postRoutes from './postRoutes';
import errorHandler from './errorHandler';
import morgan from 'morgan'; // For HTTP request logging

const app = express();
const PORT = process.env.MONGODB_APP_SERVER_PORT || 5000;

// Middleware
app.use(express.json());
app.use(morgan('dev')); // Logs HTTP requests

// Routes
app.use('/api/posts', postRoutes);

// Error Handling Middleware
app.use(errorHandler);

// Connect to MongoDB and Start Server
connectDB().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
});

0 comments on commit f111aa3

Please sign in to comment.