UNPKG

astro-loader-prismic

Version:

A simple loader to load data from a Prismic CMS into Astro using the Astro Loader API introduced in Astro 5.

101 lines (89 loc) 3.23 kB
import { z, type ZodTypeAny } from "zod"; import { asHTML, asText } from "@prismicio/client"; export function schematize(metadata: any) { const schema: Record<string, ZodTypeAny> = { id: z.string(), slug: z.string() } for (let type in metadata) { schema[type] = parseType(metadata[type]); } return z.object(schema); } function parseType(struct: TypeStruct): ZodTypeAny { if (struct.type == "Boolean") return z.boolean().nullable().default(false); if (struct.type == "Number") return z.number().default(0); if (struct.type == "StructuredText") { return z.object({ text: z.string(), rendered: z.string() }).or(z.string()).nullable() } if (struct.type == "Link") { return z.object({ id: z.string(), slug: z.string() }).nullable(); } if (struct.type == "Image") { return z.object({ url: z.string().nullable(), alt: z.string().nullable() }).nullable(); } if (struct.type == "Group") { return z.array(z.any()); } return z.any(); } export function parsePrismicDoc( data_: Record<string, any>, schema: Record<string, any> ): Record<string, any> { const data: Record<string, any> = {} for (let field in data_) { const metadata = data_[field]; const datatype = schema[field]; if (!metadata || !datatype) { data[field] = null; } else if (datatype.type == "Group") { const array = []; for (let item of metadata) { array.push(parsePrismicDoc(item, datatype.config.fields)); } data[field] = array; } else if (datatype.type == "Slices") { const slices = []; const sliceTypes = datatype.config.choices; for (let slice of metadata) { const type = slice.slice_type; const main = parsePrismicDoc( slice.primary, sliceTypes[type]["non-repeat"] ) const items = []; for (let item of slice.items) { items.push( parsePrismicDoc(item, sliceTypes[type].repeat) ); } slices.push({ ...main, items, type }) } data[field] = slices; } else if (datatype.type == "Link") { const { id, slug } = metadata; if (!id) data[field] = null; else data[field] = { id, slug }; } else if (datatype.type == "Image") { const { url, alt } = metadata; if (url) data[field] = { url, alt } else data[field] = null } else if (datatype.type == "StructuredText") { const isSingle = "single" in datatype.config; if (isSingle) data[field] = asText(metadata); else data[field] = { text: asText(metadata), rendered: asHTML(metadata) } } else data[field] = metadata; } return data }