thomaswilson-sveltekit/src/lib/snout-street-studios/SnoutStreetStudiosPost.ts

74 lines
2.2 KiB
TypeScript

import { z } from 'zod';
import type { SnoutStreetStudiosPostDto } from './SnoutStreetStudiosPostDto.js';
const SnoutStreetStudiosPostProps = z.object({
slug: z.string(),
title: z.string(),
date: z.date(),
html: z.string(),
});
// Make a props type from the zod schema, where the values are non-optional.
type Props = z.infer<typeof SnoutStreetStudiosPostProps> & {
excerpt: string;
html: string;
};
export class SnoutStreetStudiosPost {
public readonly slug: string;
public readonly title: string;
public readonly date: Date;
public readonly html: string;
public readonly excerpt: string;
constructor(props: Props) {
try {
const { slug, title, date, html } = SnoutStreetStudiosPostProps.parse(props);
this.slug = slug;
this.title = title;
this.date = date;
this.html = html;
this.excerpt = props.excerpt;
} catch (error) {
SnoutStreetStudiosPost.logAndThenThrowError(`Failed to construct post`, 'constructor', { props, error });
throw error;
}
}
private static logAndThenThrowError(errorMessage: string, contextName: string, ...args: any) {
console.error({
info: `Caught error in SnoutStreetStudiosPost::${contextName}`,
errorMessage,
...args,
});
throw new Error(errorMessage);
}
public toJson(): string {
const dto: SnoutStreetStudiosPostDto = {
slug: this.slug,
title: this.title,
date: this.date,
html: this.html,
excerpt: this.excerpt,
};
return JSON.stringify(dto);
}
public static fromJson(json: string): SnoutStreetStudiosPost {
try {
JSON.parse(json);
} catch {
this.logAndThenThrowError('Failed to parse JSON', 'fromJson', { json });
}
try {
const dto: SnoutStreetStudiosPostDto = JSON.parse(json);
return new SnoutStreetStudiosPost(dto);
} catch {
this.logAndThenThrowError(`Failed to construct post from JSON`, 'fromJson', { json });
}
}
}