All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 28s
141 lines
3.6 KiB
TypeScript
141 lines
3.6 KiB
TypeScript
import clientPromise from "./mongodb";
|
|
import { ObjectId } from "mongodb";
|
|
|
|
export interface BlogPost {
|
|
_id?: ObjectId;
|
|
title: string;
|
|
slug: string;
|
|
excerpt: string;
|
|
content: string;
|
|
author: string;
|
|
category: "case-study" | "blog";
|
|
tags: string[];
|
|
coverImage?: string;
|
|
publishedAt: Date;
|
|
updatedAt: Date;
|
|
featured: boolean;
|
|
seo?: {
|
|
title?: string;
|
|
description?: string;
|
|
keywords?: string[];
|
|
};
|
|
}
|
|
|
|
const DB_NAME = "mo1124_ai_web";
|
|
const COLLECTION_NAME = "posts";
|
|
|
|
// Helper function to serialize MongoDB documents for client components
|
|
function serializePost(post: any): BlogPost {
|
|
return {
|
|
...post,
|
|
_id: post._id?.toString(),
|
|
// Normalize author to always be a string
|
|
author:
|
|
typeof post.author === "string"
|
|
? post.author
|
|
: post.author?.name || "Unknown",
|
|
// Normalize tags to always be an array
|
|
tags: Array.isArray(post.tags)
|
|
? post.tags
|
|
: typeof post.tags === "string"
|
|
? post.tags.trim().startsWith("[")
|
|
? JSON.parse(post.tags)
|
|
: [post.tags]
|
|
: [],
|
|
publishedAt:
|
|
post.publishedAt instanceof Date
|
|
? post.publishedAt
|
|
: new Date(post.publishedAt),
|
|
updatedAt:
|
|
post.updatedAt instanceof Date
|
|
? post.updatedAt
|
|
: new Date(post.updatedAt),
|
|
};
|
|
}
|
|
|
|
export async function getAllPosts(
|
|
category?: "case-study" | "blog",
|
|
): Promise<BlogPost[]> {
|
|
console.log("[Blog] 📚 Fetching posts...", { category: category || "all" });
|
|
try {
|
|
const client = await clientPromise;
|
|
const db = client.db(DB_NAME);
|
|
|
|
const query = category ? { category } : {};
|
|
console.log("[Blog] 🔍 Query:", query);
|
|
|
|
const posts = await db
|
|
.collection<BlogPost>(COLLECTION_NAME)
|
|
.find(query)
|
|
.sort({ publishedAt: -1 })
|
|
.toArray();
|
|
|
|
console.log("[Blog] ✅ Posts fetched:", posts.length);
|
|
return posts.map(serializePost);
|
|
} catch (error) {
|
|
console.error("Database Error:", error);
|
|
console.warn("MongoDB connection failed, returning empty posts array");
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export async function getPostBySlug(slug: string): Promise<BlogPost | null> {
|
|
try {
|
|
const client = await clientPromise;
|
|
const db = client.db(DB_NAME);
|
|
|
|
const post = await db
|
|
.collection<BlogPost>(COLLECTION_NAME)
|
|
.findOne({ slug });
|
|
|
|
return post ? serializePost(post) : null;
|
|
} catch (error) {
|
|
console.error("Database Error:", error);
|
|
console.warn("MongoDB connection failed, returning null for post");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function getFeaturedPosts(limit: number = 3): Promise<BlogPost[]> {
|
|
try {
|
|
const client = await clientPromise;
|
|
const db = client.db(DB_NAME);
|
|
|
|
const posts = await db
|
|
.collection<BlogPost>(COLLECTION_NAME)
|
|
.find({ featured: true })
|
|
.sort({ publishedAt: -1 })
|
|
.limit(limit)
|
|
.toArray();
|
|
|
|
return posts.map(serializePost);
|
|
} catch (error) {
|
|
console.error("Database Error:", error);
|
|
console.warn("MongoDB connection failed, returning empty featured posts");
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export async function getPostsByCategory(
|
|
category: "case-study" | "blog",
|
|
): Promise<BlogPost[]> {
|
|
try {
|
|
const client = await clientPromise;
|
|
const db = client.db(DB_NAME);
|
|
|
|
const posts = await db
|
|
.collection<BlogPost>(COLLECTION_NAME)
|
|
.find({ category })
|
|
.sort({ publishedAt: -1 })
|
|
.toArray();
|
|
|
|
return posts.map(serializePost);
|
|
} catch (error) {
|
|
console.error("Database Error:", error);
|
|
console.warn(
|
|
"MongoDB connection failed, returning empty posts by category",
|
|
);
|
|
return [];
|
|
}
|
|
}
|