femto-webapp/src/app/feed/posts/postsService.ts
2025-08-10 18:08:17 +02:00

88 lines
2 KiB
TypeScript

import { Post } from './posts.ts'
import { ApiClient } from '../../api/client.ts'
export class PostsService {
constructor(private readonly client: ApiClient) {}
async createNew(
authorId: string,
content: string,
media: CreatePostMedia[],
isPublic: boolean,
): Promise<Post> {
const response = await this.client.POST('/posts', {
body: {
authorId,
content,
media: media.map((m) => {
return { ...m, type: null, url: m.url.toString() }
}),
isPublic,
},
credentials: 'include',
})
if (!response.data) {
throw new Error('Failed to create post')
}
return Post.fromDto(response.data.post)
}
async load(postId: string): Promise<Post | null> {
const response = await this.client.GET('/posts/{postId}', {
params: {
path: { postId },
},
credentials: 'include',
})
if (!response.data?.post) {
return null
}
return Post.fromDto(response.data.post)
}
async loadPublicFeed(cursor: string | null, amount: number | null): Promise<{ posts: Post[] }> {
const response = await this.client.GET('/posts', {
params: {
query: { After: cursor ?? undefined, Amount: amount ?? undefined },
},
credentials: 'include',
})
if (!response.data) {
return { posts: [] }
}
return { posts: response.data.posts.map(Post.fromDto) }
}
async addReaction(postId: string, emoji: string): Promise<void> {
await this.client.POST('/posts/{postId}/reactions', {
params: {
path: { postId },
},
body: { emoji },
credentials: 'include',
})
}
async removeReaction(postId: string, emoji: string): Promise<void> {
await this.client.DELETE('/posts/{postId}/reactions', {
params: {
path: { postId },
},
body: { emoji },
credentials: 'include',
})
}
}
interface CreatePostMedia {
mediaId: string
url: string | URL
width: number | null
height: number | null
}