Add "Playing It Safe" draft and improve type-checking

- Remove most type assertions and improve types
- Validate wordCount property
- Add "Vore Day" tag
- Add licenses
This commit is contained in:
Bad Manners 2024-08-03 20:33:49 -03:00
parent 17ef8c652c
commit fe908a4989
37 changed files with 1309 additions and 841 deletions

View file

@ -16,8 +16,8 @@ export const WEBSITE_LIST = [
] as const;
export const GAME_PLATFORMS = ["web", "windows", "linux", "macos", "android", "ios"] as const;
export const DEFAULT_LANG = "eng";
export const DEFAULT_AUTHOR = "bad-manners";
export const ANONYMOUS_USER = "anonymous";
export const DEFAULT_AUTHOR_ID = "bad-manners";
export const ANONYMOUS_USER_ID = "anonymous";
// Validators
@ -40,9 +40,10 @@ const refineCopyrightedCharacters = [
// Transformers
export const adjustDateForUTCOffset = (date: Date) =>
const trimText = (text: string) => text.trim();
const adjustDateForUTCOffset = (date: Date) =>
new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
export const parseMastodonPostUrl = (url: string, ctx: z.RefinementCtx) => {
const parseMastodonPostUrl = (url: string, ctx: z.RefinementCtx) => {
const match = mastodonPostUrlRegex.exec(url);
if (!match) {
ctx.addIssue({
@ -70,14 +71,17 @@ const mastodonPost = z
postId: z.string(),
})
.or(z.string().transform(parseMastodonPostUrl));
const authors = z
.union([reference("users"), z.array(reference("users"))])
.default(DEFAULT_AUTHOR)
.refine(...refineAuthors);
const userList = z
.array(reference("users"))
.or(reference("users").transform((user) => [user]))
.refine((value) => value.length > 0, `user list cannot be empty`);
const authors = userList.default([DEFAULT_AUTHOR_ID]);
const copyrightedCharacters = z
.record(z.string(), reference("users"))
.default({})
.refine(...refineCopyrightedCharacters);
// { eng: string, tok?: string, ... }
const langRecord = z.object({ [DEFAULT_LANG]: z.string() }).and(z.record(lang, z.string()));
export type Lang = z.output<typeof lang>;
export type Website = z.infer<typeof website>;
@ -93,21 +97,21 @@ const storiesCollection = defineCollection({
// Required
title: z.string(),
wordCount: z.number().int().optional(),
contentWarning: z.string(),
description: z.string(),
contentWarning: z.string().transform(trimText),
description: z.string().transform(trimText),
tags: z.array(z.string()),
// Optional
pubDate: z.date().transform(adjustDateForUTCOffset).optional(),
isDraft: z.boolean().default(false),
shortTitle: z.string().optional(),
authors,
summary: z.string().optional(),
summary: z.string().transform(trimText).optional(),
thumbnail: image().optional(),
thumbnailWidth: z.number().int().optional(),
thumbnailHeight: z.number().int().optional(),
series: reference("series").optional(),
commissioner: reference("users").optional(),
requester: reference("users").optional(),
commissioner: userList.optional(),
requester: userList.optional(),
copyrightedCharacters: copyrightedCharacters,
lang,
prev: reference("stories").nullish(),
@ -134,8 +138,9 @@ const gamesCollection = defineCollection({
z.object({
// Required
title: z.string(),
contentWarning: z.string(),
description: z.string(),
contentWarning: z.string().transform(trimText),
description: z.string().transform(trimText),
platforms: z.array(platform).refine((platforms) => platforms.length > 0, `"platforms" cannot be empty`),
tags: z.array(z.string()),
// Optional
pubDate: z.date().transform(adjustDateForUTCOffset).optional(),
@ -145,7 +150,6 @@ const gamesCollection = defineCollection({
thumbnailWidth: z.number().int().optional(),
thumbnailHeight: z.number().int().optional(),
series: reference("series").optional(),
platforms: z.array(platform).refine((platforms) => platforms.length > 0, `"platforms" cannot be empty`),
copyrightedCharacters: copyrightedCharacters,
lang,
relatedStories: z.array(reference("stories")).default([]),
@ -176,7 +180,7 @@ const usersCollection = defineCollection({
links: z.record(website, z.union([z.string().url(), z.tuple([z.string().url(), z.string()])])),
// Optional
preferredLink: website.nullish(),
lang: z.record(lang, z.string()).default({}),
lang: langRecord.optional(),
avatar: image().optional(),
})
.refine(
@ -205,7 +209,7 @@ const tagCategoriesCollection = defineCollection({
index: z.number().int(),
tags: z.array(
z.object({
name: z.union([z.string(), z.object({ [DEFAULT_LANG]: z.string() }).and(z.record(lang, z.string()))]),
name: z.union([z.string(), langRecord]),
description: z.string().optional(),
related: z.array(z.string()).optional(),
}),