a tool for shared writing and social publishing
1import { Agent, lexToJson } from "@atproto/api";
2import { PostView } from "@atproto/api/dist/client/types/app/bsky/feed/defs";
3import { NextRequest } from "next/server";
4
5export const runtime = "nodejs";
6
7export async function GET(req: NextRequest) {
8 try {
9 const searchParams = req.nextUrl.searchParams;
10 const urisParam = searchParams.get("uris");
11
12 if (!urisParam) {
13 return Response.json(
14 { error: "uris parameter is required" },
15 { status: 400 },
16 );
17 }
18
19 // Parse URIs from JSON string
20 let uris: string[];
21 try {
22 uris = JSON.parse(urisParam);
23 } catch (e) {
24 return Response.json(
25 { error: "uris must be valid JSON array" },
26 { status: 400 },
27 );
28 }
29
30 if (!Array.isArray(uris)) {
31 return Response.json({ error: "uris must be an array" }, { status: 400 });
32 }
33
34 if (uris.length === 0) {
35 return Response.json([], {
36 headers: {
37 "Cache-Control": "public, s-maxage=600, stale-while-revalidate=3600",
38 },
39 });
40 }
41
42 // Hydrate Bluesky URIs with post data
43 let agent = new Agent({
44 service: "https://public.api.bsky.app",
45 });
46
47 // Process URIs in batches of 25
48 let allPostRequests = [];
49 for (let i = 0; i < uris.length; i += 25) {
50 let batch = uris.slice(i, i + 25);
51 let batchPosts = agent.getPosts(
52 {
53 uris: batch,
54 },
55 { headers: {} },
56 );
57 allPostRequests.push(batchPosts);
58 }
59 let allPosts = (await Promise.all(allPostRequests)).flatMap(
60 (r) => r.data.posts,
61 );
62
63 const posts = lexToJson(allPosts) as PostView[];
64
65 return Response.json(posts, {
66 headers: {
67 // Cache for 1 hour on CDN, allow stale content for 24 hours while revalidating
68 "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=86400",
69 },
70 });
71 } catch (error) {
72 console.error("Error hydrating Bluesky posts:", error);
73 return Response.json({ error: "Failed to hydrate posts" }, { status: 500 });
74 }
75}