@seriphxyz/astro 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +8 -63
- package/dist/index.js +14 -111
- package/dist/loader.d.ts +5 -53
- package/dist/loader.js +5 -75
- package/package.json +15 -9
- package/src/Subscribe.astro +302 -0
- package/src/SubscribeForm.astro +142 -0
- package/src/index.ts +65 -206
- package/src/loader.ts +19 -150
package/src/index.ts
CHANGED
|
@@ -1,212 +1,71 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @seriphxyz/astro
|
|
3
|
+
*
|
|
4
|
+
* Astro components and content loader for Seriph widgets.
|
|
5
|
+
* Re-exports all types, API functions, and controllers from @seriphxyz/core.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Re-export everything from core
|
|
9
|
+
export {
|
|
10
|
+
// Constants
|
|
11
|
+
DEFAULT_ENDPOINT,
|
|
12
|
+
API_PATH,
|
|
13
|
+
|
|
14
|
+
// Types
|
|
15
|
+
type SeriphConfig,
|
|
16
|
+
type Comment,
|
|
17
|
+
type ReactionCounts,
|
|
18
|
+
type FormSubmitResponse,
|
|
19
|
+
type SubscribeResponse,
|
|
20
|
+
type SeriphPost,
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
// Helpers
|
|
23
|
+
buildUrl,
|
|
24
|
+
getSiteKey,
|
|
25
|
+
|
|
26
|
+
// API Functions - Forms
|
|
27
|
+
type SubmitFormOptions,
|
|
28
|
+
submitForm,
|
|
29
|
+
|
|
30
|
+
// API Functions - Comments
|
|
31
|
+
type FetchCommentsOptions,
|
|
32
|
+
fetchComments,
|
|
33
|
+
type PostCommentOptions,
|
|
34
|
+
postComment,
|
|
35
|
+
|
|
36
|
+
// API Functions - Reactions
|
|
37
|
+
type FetchReactionsOptions,
|
|
38
|
+
fetchReactions,
|
|
39
|
+
type AddReactionOptions,
|
|
40
|
+
addReaction,
|
|
41
|
+
type RemoveReactionOptions,
|
|
42
|
+
removeReaction,
|
|
43
|
+
|
|
44
|
+
// API Functions - Subscriptions
|
|
45
|
+
type SubscribeOptions,
|
|
46
|
+
subscribe,
|
|
47
|
+
|
|
48
|
+
// API Functions - Posts
|
|
49
|
+
type FetchPostsOptions,
|
|
50
|
+
fetchPosts,
|
|
51
|
+
type FetchPostOptions,
|
|
52
|
+
fetchPost,
|
|
16
53
|
|
|
17
|
-
//
|
|
54
|
+
// Controllers
|
|
55
|
+
type ControllerStatus,
|
|
56
|
+
type ControllerListener,
|
|
57
|
+
type SubscribeState,
|
|
58
|
+
type FormState,
|
|
59
|
+
type ReactionsState,
|
|
60
|
+
type CommentsState,
|
|
61
|
+
SubscribeController,
|
|
62
|
+
FormController,
|
|
63
|
+
ReactionsController,
|
|
64
|
+
CommentsController,
|
|
65
|
+
} from "@seriphxyz/core";
|
|
66
|
+
|
|
67
|
+
// Re-export loader (Astro-specific)
|
|
18
68
|
export {
|
|
19
69
|
seriphPostsLoader,
|
|
20
|
-
seraphPostsLoader,
|
|
21
|
-
fetchPosts,
|
|
22
|
-
fetchPost,
|
|
23
|
-
type SeriphPost,
|
|
24
|
-
type SeraphPost,
|
|
25
70
|
type SeriphPostsLoaderOptions,
|
|
26
|
-
type SeraphPostsLoaderOptions,
|
|
27
|
-
type FetchPostsOptions,
|
|
28
|
-
type FetchPostOptions,
|
|
29
71
|
} from "./loader.js";
|
|
30
|
-
|
|
31
|
-
export interface FormSubmitOptions {
|
|
32
|
-
onSuccess?: (data: unknown) => void;
|
|
33
|
-
onError?: (error: Error) => void;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface Comment {
|
|
37
|
-
id: string;
|
|
38
|
-
pageId: string;
|
|
39
|
-
parentId?: string;
|
|
40
|
-
authorName: string;
|
|
41
|
-
content: string;
|
|
42
|
-
createdAt: string;
|
|
43
|
-
replies: Comment[];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface ReactionCounts {
|
|
47
|
-
pageId: string;
|
|
48
|
-
counts: Record<string, number>;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Helper to build API URL
|
|
52
|
-
function buildUrl(endpoint: string | undefined, path: string): string {
|
|
53
|
-
const base = (endpoint || DEFAULT_ENDPOINT).replace(/\/+$/, "");
|
|
54
|
-
return `${base}${API_PATH}${path}`;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Helper to get site key (supports both siteKey and deprecated apiKey)
|
|
58
|
-
function getSiteKey(config: SeriphConfig): string {
|
|
59
|
-
const key = config.siteKey || config.apiKey;
|
|
60
|
-
if (!key) {
|
|
61
|
-
throw new Error("siteKey is required");
|
|
62
|
-
}
|
|
63
|
-
return key;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface SubmitFormOptions extends SeriphConfig {
|
|
67
|
-
formSlug: string;
|
|
68
|
-
data: Record<string, unknown>;
|
|
69
|
-
/** Form load timestamp for spam detection (auto-set if not provided) */
|
|
70
|
-
formLoadTime?: number;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface FormSubmitResponse {
|
|
74
|
-
success: boolean;
|
|
75
|
-
message: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Client utilities
|
|
79
|
-
export async function submitForm(options: SubmitFormOptions): Promise<FormSubmitResponse> {
|
|
80
|
-
const { endpoint, formSlug, data, formLoadTime } = options;
|
|
81
|
-
const siteKey = getSiteKey(options);
|
|
82
|
-
const url = buildUrl(endpoint, `/forms/${formSlug}/submit`);
|
|
83
|
-
|
|
84
|
-
// Include timestamp for time-based spam detection
|
|
85
|
-
const payload = {
|
|
86
|
-
...data,
|
|
87
|
-
_seriph_ts: formLoadTime || Math.floor(Date.now() / 1000),
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const response = await fetch(url, {
|
|
91
|
-
method: "POST",
|
|
92
|
-
headers: {
|
|
93
|
-
"Content-Type": "application/json",
|
|
94
|
-
"X-Seriph-Key": siteKey,
|
|
95
|
-
},
|
|
96
|
-
body: JSON.stringify(payload),
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
if (!response.ok) {
|
|
100
|
-
throw new Error(`Form submission failed: ${response.statusText}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return response.json();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface FetchCommentsOptions extends SeriphConfig {
|
|
107
|
-
pageId: string;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export async function fetchComments(options: FetchCommentsOptions): Promise<Comment[]> {
|
|
111
|
-
const { endpoint, pageId } = options;
|
|
112
|
-
const siteKey = getSiteKey(options);
|
|
113
|
-
const url = buildUrl(endpoint, `/comments/${encodeURIComponent(pageId)}`);
|
|
114
|
-
|
|
115
|
-
const response = await fetch(url, {
|
|
116
|
-
headers: {
|
|
117
|
-
"X-Seriph-Key": siteKey,
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
if (!response.ok) {
|
|
122
|
-
throw new Error(`Failed to fetch comments: ${response.statusText}`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const data = await response.json();
|
|
126
|
-
return data.data || [];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export interface PostCommentOptions extends SeriphConfig {
|
|
130
|
-
pageId: string;
|
|
131
|
-
authorName: string;
|
|
132
|
-
authorEmail?: string;
|
|
133
|
-
content: string;
|
|
134
|
-
parentId?: string;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export async function postComment(options: PostCommentOptions): Promise<Comment> {
|
|
138
|
-
const { endpoint, pageId, ...rest } = options;
|
|
139
|
-
const siteKey = getSiteKey(options);
|
|
140
|
-
const url = buildUrl(endpoint, `/comments/${encodeURIComponent(pageId)}`);
|
|
141
|
-
|
|
142
|
-
const response = await fetch(url, {
|
|
143
|
-
method: "POST",
|
|
144
|
-
headers: {
|
|
145
|
-
"Content-Type": "application/json",
|
|
146
|
-
"X-Seriph-Key": siteKey,
|
|
147
|
-
},
|
|
148
|
-
body: JSON.stringify({
|
|
149
|
-
authorName: rest.authorName,
|
|
150
|
-
authorEmail: rest.authorEmail,
|
|
151
|
-
content: rest.content,
|
|
152
|
-
parentId: rest.parentId,
|
|
153
|
-
}),
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
if (!response.ok) {
|
|
157
|
-
throw new Error(`Failed to post comment: ${response.statusText}`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const data = await response.json();
|
|
161
|
-
return data.data;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export interface FetchReactionsOptions extends SeriphConfig {
|
|
165
|
-
pageId: string;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export async function fetchReactions(options: FetchReactionsOptions): Promise<ReactionCounts> {
|
|
169
|
-
const { endpoint, pageId } = options;
|
|
170
|
-
const siteKey = getSiteKey(options);
|
|
171
|
-
const url = buildUrl(endpoint, `/reactions/${encodeURIComponent(pageId)}`);
|
|
172
|
-
|
|
173
|
-
const response = await fetch(url, {
|
|
174
|
-
headers: {
|
|
175
|
-
"X-Seriph-Key": siteKey,
|
|
176
|
-
},
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
if (!response.ok) {
|
|
180
|
-
throw new Error(`Failed to fetch reactions: ${response.statusText}`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const data = await response.json();
|
|
184
|
-
return data.data;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export interface AddReactionOptions extends SeriphConfig {
|
|
188
|
-
pageId: string;
|
|
189
|
-
reactionType?: string;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export async function addReaction(options: AddReactionOptions): Promise<{ reactionType: string; count: number }> {
|
|
193
|
-
const { endpoint, pageId, reactionType = "like" } = options;
|
|
194
|
-
const siteKey = getSiteKey(options);
|
|
195
|
-
const url = buildUrl(endpoint, `/reactions/${encodeURIComponent(pageId)}`);
|
|
196
|
-
|
|
197
|
-
const response = await fetch(url, {
|
|
198
|
-
method: "POST",
|
|
199
|
-
headers: {
|
|
200
|
-
"Content-Type": "application/json",
|
|
201
|
-
"X-Seriph-Key": siteKey,
|
|
202
|
-
},
|
|
203
|
-
body: JSON.stringify({ reactionType }),
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
if (!response.ok) {
|
|
207
|
-
throw new Error(`Failed to add reaction: ${response.statusText}`);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const data = await response.json();
|
|
211
|
-
return data.data;
|
|
212
|
-
}
|
package/src/loader.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @example
|
|
7
7
|
* // In src/content.config.ts
|
|
8
8
|
* import { defineCollection } from 'astro:content';
|
|
9
|
-
* import { seriphPostsLoader } from '
|
|
9
|
+
* import { seriphPostsLoader } from '@seriphxyz/astro/loader';
|
|
10
10
|
*
|
|
11
11
|
* const posts = defineCollection({
|
|
12
12
|
* loader: seriphPostsLoader({
|
|
@@ -17,30 +17,24 @@
|
|
|
17
17
|
* export const collections = { posts };
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** @deprecated Use SeriphPost instead */
|
|
37
|
-
export type SeraphPost = SeriphPost;
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_ENDPOINT,
|
|
22
|
+
API_PATH,
|
|
23
|
+
getSiteKey,
|
|
24
|
+
fetchPosts as coreFetchPosts,
|
|
25
|
+
fetchPost as coreFetchPost,
|
|
26
|
+
type SeriphPost,
|
|
27
|
+
type FetchPostsOptions,
|
|
28
|
+
type FetchPostOptions,
|
|
29
|
+
} from "@seriphxyz/core";
|
|
30
|
+
|
|
31
|
+
// Re-export types and functions from core
|
|
32
|
+
export type { SeriphPost, FetchPostsOptions, FetchPostOptions };
|
|
33
|
+
export { coreFetchPosts as fetchPosts, coreFetchPost as fetchPost };
|
|
38
34
|
|
|
39
35
|
export interface SeriphPostsLoaderOptions {
|
|
40
36
|
/** Your site key (required) */
|
|
41
|
-
siteKey
|
|
42
|
-
/** @deprecated Use siteKey instead */
|
|
43
|
-
apiKey?: string;
|
|
37
|
+
siteKey: string;
|
|
44
38
|
/** Base URL of your Seriph instance (default: 'https://seriph.xyz') */
|
|
45
39
|
endpoint?: string;
|
|
46
40
|
/** Filter posts by tag */
|
|
@@ -51,9 +45,6 @@ export interface SeriphPostsLoaderOptions {
|
|
|
51
45
|
onError?: "throw" | "warn" | "ignore";
|
|
52
46
|
}
|
|
53
47
|
|
|
54
|
-
/** @deprecated Use SeriphPostsLoaderOptions instead */
|
|
55
|
-
export type SeraphPostsLoaderOptions = SeriphPostsLoaderOptions;
|
|
56
|
-
|
|
57
48
|
interface LoaderContext {
|
|
58
49
|
store: {
|
|
59
50
|
set: (entry: { id: string; data: SeriphPost }) => void;
|
|
@@ -68,30 +59,10 @@ interface LoaderContext {
|
|
|
68
59
|
}
|
|
69
60
|
|
|
70
61
|
interface ApiResponse {
|
|
71
|
-
posts:
|
|
72
|
-
id: string;
|
|
73
|
-
title: string;
|
|
74
|
-
slug: string;
|
|
75
|
-
content: string;
|
|
76
|
-
excerpt?: string;
|
|
77
|
-
coverImage?: string;
|
|
78
|
-
metaTitle?: string;
|
|
79
|
-
metaDescription?: string;
|
|
80
|
-
tags: string[];
|
|
81
|
-
publishedAt: string;
|
|
82
|
-
}>;
|
|
62
|
+
posts: SeriphPost[];
|
|
83
63
|
total: number;
|
|
84
64
|
}
|
|
85
65
|
|
|
86
|
-
// Helper to get site key (supports both siteKey and deprecated apiKey)
|
|
87
|
-
function getSiteKey(options: SeriphPostsLoaderOptions): string {
|
|
88
|
-
const key = options.siteKey || options.apiKey;
|
|
89
|
-
if (!key) {
|
|
90
|
-
throw new Error("siteKey is required");
|
|
91
|
-
}
|
|
92
|
-
return key;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
66
|
/**
|
|
96
67
|
* Creates an Astro content loader that fetches posts from Seriph.
|
|
97
68
|
*
|
|
@@ -105,9 +76,7 @@ export function seriphPostsLoader(options: SeriphPostsLoaderOptions) {
|
|
|
105
76
|
onError = "throw",
|
|
106
77
|
} = options;
|
|
107
78
|
|
|
108
|
-
const siteKey = getSiteKey(options);
|
|
109
|
-
|
|
110
|
-
// Build the base API URL (strip trailing slash, add API path)
|
|
79
|
+
const siteKey = getSiteKey({ siteKey: options.siteKey });
|
|
111
80
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
112
81
|
|
|
113
82
|
return {
|
|
@@ -117,7 +86,6 @@ export function seriphPostsLoader(options: SeriphPostsLoaderOptions) {
|
|
|
117
86
|
const { store, logger } = context;
|
|
118
87
|
|
|
119
88
|
try {
|
|
120
|
-
// Build the URL with query parameters
|
|
121
89
|
const url = new URL(`${baseUrl}/posts`);
|
|
122
90
|
url.searchParams.set("limit", String(limit));
|
|
123
91
|
if (tag) {
|
|
@@ -140,25 +108,12 @@ export function seriphPostsLoader(options: SeriphPostsLoaderOptions) {
|
|
|
140
108
|
|
|
141
109
|
const data: ApiResponse = await response.json();
|
|
142
110
|
|
|
143
|
-
// Clear previous entries
|
|
144
111
|
store.clear();
|
|
145
112
|
|
|
146
|
-
// Add each post as an entry
|
|
147
113
|
for (const post of data.posts) {
|
|
148
114
|
store.set({
|
|
149
115
|
id: post.slug,
|
|
150
|
-
data:
|
|
151
|
-
id: post.id,
|
|
152
|
-
title: post.title,
|
|
153
|
-
slug: post.slug,
|
|
154
|
-
content: post.content,
|
|
155
|
-
excerpt: post.excerpt,
|
|
156
|
-
coverImage: post.coverImage,
|
|
157
|
-
metaTitle: post.metaTitle,
|
|
158
|
-
metaDescription: post.metaDescription,
|
|
159
|
-
tags: post.tags,
|
|
160
|
-
publishedAt: post.publishedAt,
|
|
161
|
-
},
|
|
116
|
+
data: post,
|
|
162
117
|
});
|
|
163
118
|
}
|
|
164
119
|
|
|
@@ -172,93 +127,7 @@ export function seriphPostsLoader(options: SeriphPostsLoaderOptions) {
|
|
|
172
127
|
} else if (onError === "warn") {
|
|
173
128
|
logger.warn(`Error loading posts (continuing anyway): ${message}`);
|
|
174
129
|
}
|
|
175
|
-
// onError === "ignore" - silently continue
|
|
176
130
|
}
|
|
177
131
|
},
|
|
178
132
|
};
|
|
179
133
|
}
|
|
180
|
-
|
|
181
|
-
/** @deprecated Use seriphPostsLoader instead (note the 'i' in seriph) */
|
|
182
|
-
export const seraphPostsLoader = seriphPostsLoader;
|
|
183
|
-
|
|
184
|
-
export interface FetchPostsOptions {
|
|
185
|
-
/** Your site key (required) */
|
|
186
|
-
siteKey?: string;
|
|
187
|
-
/** @deprecated Use siteKey instead */
|
|
188
|
-
apiKey?: string;
|
|
189
|
-
/** Base URL of your Seriph instance (default: 'https://seriph.xyz') */
|
|
190
|
-
endpoint?: string;
|
|
191
|
-
/** Filter posts by tag */
|
|
192
|
-
tag?: string;
|
|
193
|
-
/** Maximum number of posts to fetch (default: 500) */
|
|
194
|
-
limit?: number;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Utility function to fetch posts directly (for server-side use cases)
|
|
199
|
-
*/
|
|
200
|
-
export async function fetchPosts(options: FetchPostsOptions): Promise<SeriphPost[]> {
|
|
201
|
-
const { endpoint = DEFAULT_ENDPOINT, tag, limit = 500 } = options;
|
|
202
|
-
const siteKey = getSiteKey(options);
|
|
203
|
-
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
204
|
-
|
|
205
|
-
const url = new URL(`${baseUrl}/posts`);
|
|
206
|
-
url.searchParams.set("limit", String(limit));
|
|
207
|
-
if (tag) {
|
|
208
|
-
url.searchParams.set("tag", tag);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const response = await fetch(url.toString(), {
|
|
212
|
-
headers: {
|
|
213
|
-
"X-Seriph-Key": siteKey,
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
if (!response.ok) {
|
|
218
|
-
throw new Error(
|
|
219
|
-
`Failed to fetch posts: ${response.status} ${response.statusText}`,
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const data: ApiResponse = await response.json();
|
|
224
|
-
return data.posts;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export interface FetchPostOptions {
|
|
228
|
-
/** Your site key (required) */
|
|
229
|
-
siteKey?: string;
|
|
230
|
-
/** @deprecated Use siteKey instead */
|
|
231
|
-
apiKey?: string;
|
|
232
|
-
/** Base URL of your Seriph instance (default: 'https://seriph.xyz') */
|
|
233
|
-
endpoint?: string;
|
|
234
|
-
/** The post slug to fetch */
|
|
235
|
-
slug: string;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Utility function to fetch a single post by slug
|
|
240
|
-
*/
|
|
241
|
-
export async function fetchPost(options: FetchPostOptions): Promise<SeriphPost | null> {
|
|
242
|
-
const { endpoint = DEFAULT_ENDPOINT, slug } = options;
|
|
243
|
-
const siteKey = getSiteKey(options);
|
|
244
|
-
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
245
|
-
|
|
246
|
-
const response = await fetch(`${baseUrl}/posts/${encodeURIComponent(slug)}`, {
|
|
247
|
-
headers: {
|
|
248
|
-
"X-Seriph-Key": siteKey,
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
if (response.status === 404) {
|
|
253
|
-
return null;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (!response.ok) {
|
|
257
|
-
throw new Error(
|
|
258
|
-
`Failed to fetch post: ${response.status} ${response.statusText}`,
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const data = await response.json();
|
|
263
|
-
return data.public_post || data;
|
|
264
|
-
}
|