import { Temporal } from '@js-temporal/polyfill' import { components } from '../../api/schema.ts' import { immerable } from 'immer' export interface PostReaction { emoji: string authorName: string reactedOn: Temporal.Instant } export interface PostComment { author: string content: string postedOn: Temporal.Instant } export class Post { [immerable] = true public readonly postId: string public readonly content: string public readonly media: PostMedia[] public readonly createdAt: Temporal.Instant public readonly authorName: string public readonly reactions: PostReaction[] public readonly possibleReactions: string[] public readonly comments: PostComment[] constructor( postId: string, content: string, media: PostMedia[], createdAt: string | Temporal.Instant, authorName: string, reactions: PostReaction[], possibleReactions: string[], comments: PostComment[], ) { this.postId = postId this.content = content this.media = media this.createdAt = Temporal.Instant.from(createdAt) this.authorName = authorName this.reactions = reactions this.possibleReactions = possibleReactions this.comments = comments } public static fromDto(dto: components['schemas']['PostDto']): Post { return new Post( dto.postId, dto.content, dto.media.map((m) => new PostMediaImpl(new URL(m.url), m.width, m.height)), Temporal.Instant.from(dto.createdAt), dto.author.username, dto.reactions.map((r) => ({ ...r, reactedOn: Temporal.Instant.from(r.reactedOn) })), dto.possibleReactions, dto.comments.map((c) => ({ ...c, postedOn: Temporal.Instant.from(c.postedOn) })), ) } } export interface PostMedia { readonly url: URL readonly width: number | null readonly height: number | null } class PostMediaImpl implements PostMedia { constructor( readonly url: URL, readonly width: number | null, readonly height: number | null, ) {} }