53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
import { LOCALES } from '@sport/types';
|
|
|
|
import { anyIdSchema, slugSchema } from './common';
|
|
import { offsetPageQuerySchema } from './pagination';
|
|
|
|
const contentTranslationSchema = z.object({
|
|
slug: slugSchema,
|
|
title: z.string().trim().min(1).max(255),
|
|
excerpt: z.string().trim().max(500).nullish(),
|
|
/**
|
|
* Markdown, and required.
|
|
*
|
|
* A page with a title and no body is a broken link with extra steps — it
|
|
* renders, gets indexed, and tells a reader nothing.
|
|
*/
|
|
body: z.string().trim().min(1),
|
|
metaTitle: z.string().trim().max(255).nullish(),
|
|
metaDescription: z.string().trim().max(500).nullish(),
|
|
});
|
|
|
|
/**
|
|
* A page or post as an operator authors it.
|
|
*
|
|
* `translations` is a partial record: publishing an English-only post is a
|
|
* legitimate thing to do, and requiring every locale would mean inventing
|
|
* Vietnamese copy to get anything live.
|
|
*/
|
|
export const contentEntryInputSchema = z
|
|
.object({
|
|
type: z.enum(['PAGE', 'POST']),
|
|
status: z.enum(['DRAFT', 'PUBLISHED']).default('DRAFT'),
|
|
coverImageId: anyIdSchema.nullish(),
|
|
translations: z.partialRecord(z.enum(LOCALES), contentTranslationSchema),
|
|
})
|
|
.refine((value) => Object.keys(value.translations).length > 0, {
|
|
message: 'Write the entry in at least one language',
|
|
path: ['translations'],
|
|
});
|
|
|
|
export const contentListQuerySchema = offsetPageQuerySchema.extend({
|
|
type: z.enum(['PAGE', 'POST']).optional(),
|
|
status: z.enum(['DRAFT', 'PUBLISHED']).optional(),
|
|
q: z.string().trim().max(120).optional(),
|
|
});
|
|
|
|
export const postListQuerySchema = offsetPageQuerySchema;
|
|
|
|
export type ContentEntryInput = z.output<typeof contentEntryInputSchema>;
|
|
export type ContentListQuery = z.output<typeof contentListQuerySchema>;
|
|
export type PostListQuery = z.output<typeof postListQuerySchema>;
|