UNPKG

powr-sdk-api

Version:

Shared API core library for PowrStack projects. Zero dependencies - works with Express, Next.js API routes, and other frameworks. All features are optional and install only what you need.

352 lines (341 loc) 7.8 kB
"use strict"; const express = require('express'); const router = express.Router(); const { getDb } = require('../services/mongo'); const { ObjectId } = require('mongodb'); // Create new post router.post('/', async (req, res) => { try { const { content, media, isPublic = true, tags, mentions } = req.body; const projectId = req.projectId; const userId = req.user.powrId; if (!content && (!media || media.length === 0)) { return res.status(400).json({ success: false, message: 'Content or media is required' }); } const db = await getDb(); const newPost = { projectId, authorId: new ObjectId(userId), content: content || '', media: media || [], likesCount: 0, commentsCount: 0, isPublic, tags: tags || [], mentions: mentions ? mentions.map(id => new ObjectId(id)) : [], createdAt: new Date(), updatedAt: new Date() }; const result = await db.collection('feeds').insertOne(newPost); // Populate author info const author = await db.collection('users').findOne({ _id: new ObjectId(userId) }, { projection: { fullName: 1, email: 1, avatar: 1 } }); const createdPost = { ...newPost, _id: result.insertedId, author }; return res.status(201).json({ success: true, message: 'Post created successfully', data: createdPost }); } catch (error) { console.error('Error creating post:', error); return res.status(500).json({ success: false, message: 'Failed to create post' }); } }); // Get feed with pagination and filters router.get('/', async (req, res) => { try { const { page = 1, limit = 10, userId, tag, search } = req.query; const projectId = req.projectId; const skip = (parseInt(page) - 1) * parseInt(limit); const query = { projectId }; if (userId) { query.authorId = new ObjectId(userId); } if (tag) { query.tags = { $in: [tag] }; } if (search) { query.$or = [{ content: { $regex: search, $options: 'i' } }, { tags: { $in: [new RegExp(search, 'i')] } }]; } const db = await getDb(); // Get posts with author info const posts = await db.collection('feeds').aggregate([{ $match: query }, { $sort: { createdAt: -1 } }, { $skip: skip }, { $limit: parseInt(limit) }, { $lookup: { from: 'users', localField: 'authorId', foreignField: '_id', as: 'author' } }, { $unwind: { path: '$author', preserveNullAndEmptyArrays: true } }, { $project: { 'author.password': 0, 'author.access': 0 } }]).toArray(); const total = await db.collection('feeds').countDocuments(query); return res.json({ success: true, data: posts, pagination: { page: parseInt(page), limit: parseInt(limit), total, pages: Math.ceil(total / parseInt(limit)) } }); } catch (error) { console.error('Error fetching feed:', error); return res.status(500).json({ success: false, message: 'Failed to fetch feed' }); } }); // Get single post router.get('/:id', async (req, res) => { try { const { id } = req.params; const projectId = req.projectId; const db = await getDb(); const post = await db.collection('feeds').aggregate([{ $match: { _id: new ObjectId(id), projectId } }, { $lookup: { from: 'users', localField: 'authorId', foreignField: '_id', as: 'author' } }, { $unwind: { path: '$author', preserveNullAndEmptyArrays: true } }, { $project: { 'author.password': 0, 'author.access': 0 } }]).next(); if (!post) { return res.status(404).json({ success: false, message: 'Post not found' }); } return res.json({ success: true, data: post }); } catch (error) { console.error('Error fetching post:', error); return res.status(500).json({ success: false, message: 'Failed to fetch post' }); } }); // Update post router.put('/:id', async (req, res) => { try { const { id } = req.params; const { content, media, isPublic, tags, mentions } = req.body; const projectId = req.projectId; const userId = req.user.powrId; const db = await getDb(); const post = await db.collection('feeds').findOne({ _id: new ObjectId(id), projectId, authorId: new ObjectId(userId) }); if (!post) { return res.status(404).json({ success: false, message: 'Post not found or unauthorized' }); } const updateData = { updatedAt: new Date() }; if (content !== undefined) updateData.content = content; if (media !== undefined) updateData.media = media; if (isPublic !== undefined) updateData.isPublic = isPublic; if (tags !== undefined) updateData.tags = tags; if (mentions !== undefined) updateData.mentions = mentions.map(id => new ObjectId(id)); await db.collection('feeds').updateOne({ _id: new ObjectId(id) }, { $set: updateData }); return res.json({ success: true, message: 'Post updated successfully' }); } catch (error) { console.error('Error updating post:', error); return res.status(500).json({ success: false, message: 'Failed to update post' }); } }); // Delete post router.delete('/:id', async (req, res) => { try { const { id } = req.params; const projectId = req.projectId; const userId = req.user.powrId; const db = await getDb(); const post = await db.collection('feeds').findOne({ _id: new ObjectId(id), projectId, authorId: new ObjectId(userId) }); if (!post) { return res.status(404).json({ success: false, message: 'Post not found or unauthorized' }); } await db.collection('feeds').deleteOne({ _id: new ObjectId(id) }); return res.json({ success: true, message: 'Post deleted successfully' }); } catch (error) { console.error('Error deleting post:', error); return res.status(500).json({ success: false, message: 'Failed to delete post' }); } }); // Like/unlike post router.post('/:id/like', async (req, res) => { try { const { id } = req.params; const { liked } = req.body; const projectId = req.projectId; const userId = req.user.powrId; const db = await getDb(); // Update like count const updateOperation = liked ? { $inc: { likesCount: 1 } } : { $inc: { likesCount: -1 } }; await db.collection('feeds').updateOne({ _id: new ObjectId(id), projectId }, updateOperation); // Update user's like status await db.collection('likes').updateOne({ userId: new ObjectId(userId), contentId: id, projectId }, { $set: { liked } }, { upsert: true }); return res.json({ success: true, message: liked ? 'Post liked' : 'Post unliked' }); } catch (error) { console.error('Error updating like:', error); return res.status(500).json({ success: false, message: 'Failed to update like' }); } }); module.exports = router;