|  | 
|  | 1 | +import { supabaseAdmin } from "@changes-page/supabase/admin"; | 
|  | 2 | +import { IPost } from "@changes-page/supabase/types/page"; | 
|  | 3 | +import { convertMarkdownToPlainText } from "@changes-page/utils"; | 
|  | 4 | +import type { NextApiRequest, NextApiResponse } from "next"; | 
|  | 5 | +import { allowCors } from "../../../lib/cors"; | 
|  | 6 | +import { | 
|  | 7 | +  fetchRenderData, | 
|  | 8 | +  translateHostToPageIdentifier, | 
|  | 9 | +} from "../../../lib/data"; | 
|  | 10 | +import { getPageUrl, getPostUrl } from "../../../lib/url"; | 
|  | 11 | + | 
|  | 12 | +type IPostWithUrl = Pick< | 
|  | 13 | +  IPost, | 
|  | 14 | +  "id" | "title" | "content" | "tags" | "created_at" | 
|  | 15 | +> & { url: string; plain_text_content: string }; | 
|  | 16 | + | 
|  | 17 | +async function handler( | 
|  | 18 | +  req: NextApiRequest, | 
|  | 19 | +  res: NextApiResponse<IPostWithUrl | null> | 
|  | 20 | +) { | 
|  | 21 | +  const { id } = req.query; | 
|  | 22 | +  if (!id) { | 
|  | 23 | +    res.status(404).json(null); | 
|  | 24 | +    return; | 
|  | 25 | +  } | 
|  | 26 | + | 
|  | 27 | +  await allowCors(req, res); | 
|  | 28 | + | 
|  | 29 | +  const hostname = String(req?.headers?.host); | 
|  | 30 | +  const { domain, page: url_slug } = translateHostToPageIdentifier(hostname); | 
|  | 31 | + | 
|  | 32 | +  try { | 
|  | 33 | +    const { page, settings } = await fetchRenderData( | 
|  | 34 | +      String(domain || url_slug) | 
|  | 35 | +    ); | 
|  | 36 | + | 
|  | 37 | +    if (!page) throw new Error("Page not found"); | 
|  | 38 | +    if (!settings) throw new Error("Settings not found"); | 
|  | 39 | + | 
|  | 40 | +    const pageUrl = getPageUrl(page, settings, hostname); | 
|  | 41 | + | 
|  | 42 | +    const { data, error: postsError } = await supabaseAdmin | 
|  | 43 | +      .from("posts") | 
|  | 44 | +      .select("id,title,content,tags,publication_date,updated_at,created_at") | 
|  | 45 | +      .eq("id", String(id)) | 
|  | 46 | +      .eq("page_id", String(page?.id)) | 
|  | 47 | +      .eq("status", "published") | 
|  | 48 | +      .order("publication_date", { ascending: false }) | 
|  | 49 | +      .limit(1); | 
|  | 50 | + | 
|  | 51 | +    if (postsError) { | 
|  | 52 | +      console.error("Fetch post error", postsError); | 
|  | 53 | +      throw new Error("Failed to fetch posts"); | 
|  | 54 | +    } | 
|  | 55 | + | 
|  | 56 | +    const posts = data as Array<IPost>; | 
|  | 57 | + | 
|  | 58 | +    if (!posts?.length) { | 
|  | 59 | +      res.status(404).json(null); | 
|  | 60 | +      return; | 
|  | 61 | +    } | 
|  | 62 | + | 
|  | 63 | +    const post = posts[0]; | 
|  | 64 | + | 
|  | 65 | +    res.status(200).json({ | 
|  | 66 | +      ...post, | 
|  | 67 | +      url: getPostUrl(pageUrl, post), | 
|  | 68 | +      plain_text_content: convertMarkdownToPlainText(post.content), | 
|  | 69 | +    }); | 
|  | 70 | +  } catch (e: Error | any) { | 
|  | 71 | +    console.log("Failed to fetch post [Error]", e); | 
|  | 72 | +    res.status(404).json(null); | 
|  | 73 | +  } | 
|  | 74 | +} | 
|  | 75 | + | 
|  | 76 | +export default handler; | 
0 commit comments