Files
blog/src/content/config.ts

77 lines
1.8 KiB
TypeScript

import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const symbolSchema = z.discriminatedUnion('discriminant', [
z.object({
discriminant: z.literal('font'),
value: z.object({
family: z.string(),
character: z.string(),
}),
}),
z.object({
discriminant: z.literal('svg'),
value: z.string(),
}),
]);
const seoSchema = z
.object({
title: z.string().optional(),
description: z.string().optional(),
noIndex: z.boolean().default(false),
})
.optional();
const coverSchema = z
.object({
src: z.string().optional(),
alt: z.string().optional(),
caption: z.string().optional(),
showInHeader: z.boolean().default(false),
})
.optional();
const baseArticleSchema = z.object({
title: z.string(),
summary: z.string(),
subtitle: z.string().optional(),
cover: coverSchema,
publishDate: z.date(),
updateDate: z.date().optional(),
status: z.enum(['draft', 'published', 'archived']).default('draft'),
isFeatured: z.boolean().default(false),
parent: z.string().optional(),
tags: z.array(z.string()).default([]),
relatedArticles: z.array(z.string()).default([]),
seo: seoSchema,
});
const articles = defineCollection({
loader: glob({
pattern: '**/index.mdoc',
base: './src/content/articles',
}),
schema: baseArticleSchema,
});
const pages = defineCollection({
schema: z.object({
title: z.string(),
seo: seoSchema,
}),
});
const elements = defineCollection({
loader: glob({
pattern: '**/index.mdoc',
base: './src/content/crucible/elements',
}),
schema: baseArticleSchema.extend({
category: z.enum(['prime', 'essence', 'aspect']).default('prime'),
symbol: symbolSchema,
}),
});
export const collections = { articles, pages, elements };