Improve i18n support and config validation

This commit is contained in:
Bad Manners 2024-03-30 15:04:29 -03:00
parent 4f83ae8802
commit 37db38b613
9 changed files with 152 additions and 152 deletions

View file

@ -17,6 +17,8 @@ export const WEBSITE_LIST = [
] as const;
const localUrlRegex = /^((\/?\.\.(?=\/))+|(\.(?=\/)))?\/?[a-z0-9_-]+(\/[a-z0-9_-]+)*\/?$/;
const refineAuthors = (value: { id: any } | any[]) => "id" in value || value.length > 0;
const refineCopyrightedCharacters = (value: Record<string, any>) => !("" in value) || Object.keys(value).length == 1;
const lang = z.enum(["eng", "tok"]).default("eng");
const website = z.enum(WEBSITE_LIST);
@ -43,7 +45,10 @@ const storiesCollection = defineCollection({
// Optional
isDraft: z.boolean().default(false),
shortTitle: z.string().optional(),
authors: z.union([reference("users"), z.array(reference("users"))]).default("bad-manners"),
authors: z
.union([reference("users"), z.array(reference("users"))])
.default("bad-manners")
.refine(refineAuthors, "authors cannot be empty"),
descriptionPlaintext: z.string().optional(),
summary: z.string().optional(),
thumbnail: image().optional(),
@ -52,7 +57,13 @@ const storiesCollection = defineCollection({
series: reference("series").optional(),
commissioner: reference("users").optional(),
requester: reference("users").optional(),
copyrightedCharacters: z.record(z.string(), reference("users")).default({}),
copyrightedCharacters: z
.record(z.string(), reference("users"))
.default({})
.refine(
refineCopyrightedCharacters,
"copyrightedCharacters cannot have an empty catch-all key with other keys",
),
lang,
prev: reference("stories").nullish(),
next: reference("stories").nullish(),
@ -74,13 +85,22 @@ const gamesCollection = defineCollection({
tags: z.array(z.string()),
// Optional
isDraft: z.boolean().default(false),
authors: z.union([reference("users"), z.array(reference("users"))]).default("bad-manners"),
authors: z
.union([reference("users"), z.array(reference("users"))])
.default("bad-manners")
.refine(refineAuthors, "authors cannot be empty"),
descriptionPlaintext: z.string().optional(),
thumbnail: image().optional(),
thumbnailWidth: z.number().int().optional(),
thumbnailHeight: z.number().int().optional(),
series: reference("series").optional(),
copyrightedCharacters: z.record(z.string(), reference("users")).default({}),
copyrightedCharacters: z
.record(z.string(), reference("users"))
.default({})
.refine(
refineCopyrightedCharacters,
"copyrightedCharacters cannot have an empty catch-all key with other keys",
),
lang,
relatedStories: z.array(reference("stories")).default([]),
relatedGames: z.array(reference("games")).default([]),
@ -91,16 +111,24 @@ const gamesCollection = defineCollection({
const usersCollection = defineCollection({
type: "data",
schema: ({ image }) =>
z.object({
// Required
name: z.string(),
links: z.record(website, z.union([z.string().url(), z.tuple([z.string().url(), z.string()])])),
// Optional
preferredLink: website.nullish(),
nameLang: z.record(lang, z.string()).default({}),
avatar: image().optional(),
isAnonymous: z.boolean().default(false),
}),
z
.object({
// Required
name: z.string(),
links: z.record(website, z.union([z.string().url(), z.tuple([z.string().url(), z.string()])])),
// Optional
preferredLink: website.nullish(),
nameLang: z.record(lang, z.string()).default({}),
avatar: image().optional(),
isAnonymous: z.boolean().default(false),
})
.refine(
({ links, preferredLink }) => !preferredLink || preferredLink in links,
({ preferredLink }) => ({
message: `"${preferredLink}" not defined in links`,
path: ["preferredLink"],
}),
),
});
const seriesCollection = defineCollection({
@ -118,7 +146,12 @@ const tagCategoriesCollection = defineCollection({
// Required
name: z.string(),
index: z.number().int(),
tags: z.array(z.union([z.string(), z.record(lang, z.string())])),
tags: z.array(
z.union([
z.string(),
z.record(lang, z.string()).refine((tag) => "eng" in tag, 'Object-formatted tag must have an "eng" key'),
]),
),
}),
});