import { z } from "zod/mini" import { WidgetKeySchema } from "../common/widgetKey" import type { GroupModel, NestedGroupModel } from "./group" import { GroupModelSchema, NestedGroupModelSchema } from "./group" import type { NestableModel } from "./nestable" import { NestableModelSchema } from "./nestable" // Simple (before 2020) export const LegacySliceModelSchema = z.discriminatedUnion("type", [ NestableModelSchema, NestedGroupModelSchema, ]) export type LegacySliceModel = NestableModel | NestedGroupModel // Composite (2020 to 2021) export const CompositeSliceType = "Slice" as const const CompositeSliceConfigSchema = z.object({ label: z.nullish(z.string()), }) export const CompositeSliceModelSchema = z.object({ type: z.literal(CompositeSliceType), fieldset: z.nullish(z.string()), description: z.optional(z.string()), icon: z.optional(z.string()), display: z.optional(z.string()), "non-repeat": z.optional(z.record(WidgetKeySchema, NestableModelSchema)), repeat: z.optional(z.record(WidgetKeySchema, NestableModelSchema)), config: z.optional(CompositeSliceConfigSchema), }) export type CompositeSliceModel = z.infer // Shared (2021 to present) export const SharedSliceType = "SharedSlice" as const const IMAGE_PLACEHOLDER_URL = "https://images.prismic.io/slice-machine/621a5ec4-0387-4bc5-9860-2dd46cbc07cd_default_ss.png?auto=compress,format" export const SharedSliceModelVariationSchema = z.object({ id: z.string(), name: z.string(), description: z.string(), imageUrl: z._default(z.string(), IMAGE_PLACEHOLDER_URL), docURL: z.string(), version: z.string(), display: z.optional(z.string()), primary: z.optional( z.record( z.string(), z.discriminatedUnion("type", [NestableModelSchema, GroupModelSchema]) as z.ZodMiniType< NestableModel | GroupModel >, ), ), items: z.optional(z.record(z.string(), NestableModelSchema)), }) export type SharedSliceModelVariation = z.infer // 4.4.0 and earlier const SharedSliceModelSchema_4_4_0 = z.object({ id: z.string(), type: z.literal(SharedSliceType), name: z.string(), variations: z.array(SharedSliceModelVariationSchema), description: z.optional(z.string()), legacyPaths: z.optional(z.record(z.string(), z.string())), schema: z.optional(z.undefined()), }) // 4.5.0 and later const SharedSliceModelSchema_4_5_0 = z .object({ ...SharedSliceModelSchema_4_4_0.shape, schema: z.literal("@prismicio/types-internal@4.5.0"), }) .check( z.superRefine((model, ctx) => { if (model.variations.length === 0) { ctx.addIssue({ code: "custom", message: `Shared slice "${model.id}" must have at least one variation`, path: ["variations"], }) } // A map of variation IDs to the index they belong to // to check for ID uniqueness across all variations. const existingVariationIDs = new Map() for (let index = 0; index < model.variations.length; index++) { const variation = model.variations[index] const maybeIndex = existingVariationIDs.get(variation.id) if (Number.isInteger(maybeIndex)) { ctx.addIssue({ code: "custom", message: `Variation ID "${variation.id}" already exists at index "${maybeIndex}"`, path: ["variations", index], }) continue } existingVariationIDs.set(variation.id, index) } }), ) export const SharedSliceModelSchema = z.discriminatedUnion("schema", [ SharedSliceModelSchema_4_4_0, SharedSliceModelSchema_4_5_0, ]) export type SharedSliceModel = z.infer export const SharedSliceRefModelSchema = z.object({ type: z.literal(SharedSliceType), }) export type SharedSliceRefModel = z.infer // Used to represent a shared slice content which can only be // of a given shared slice variation type. export const SharedSliceVariationContentModelSchema = z.object({ type: z.literal(SharedSliceType), sliceName: z.string(), variationID: z.string(), fields: z.pick(SharedSliceModelVariationSchema, { primary: true, items: true }), }) export type SharedSliceVariationContentModel = z.infer< typeof SharedSliceVariationContentModelSchema > // All // Used when slices reference SharedSlice by ref (not full definition) export const DynamicSliceModelSchema: z.ZodMiniType = z.discriminatedUnion( "type", [CompositeSliceModelSchema, LegacySliceModelSchema, SharedSliceRefModelSchema], ) export type DynamicSliceModel = CompositeSliceModel | LegacySliceModel | SharedSliceRefModel // Used when slices include full SharedSlice definition export const StaticSliceModelSchema: z.ZodMiniType = z.discriminatedUnion( "type", [CompositeSliceModelSchema, LegacySliceModelSchema, SharedSliceModelSchema], ) export type StaticSliceModel = CompositeSliceModel | LegacySliceModel | SharedSliceModel // Used to represent a slice content model as shared slice variations // can only be of a given shared slice variation type. export const SliceContentModelSchema: z.ZodMiniType = z.discriminatedUnion( "type", [CompositeSliceModelSchema, LegacySliceModelSchema, SharedSliceVariationContentModelSchema], ) export type SliceContentModel = | CompositeSliceModel | LegacySliceModel | SharedSliceVariationContentModel // Model types export const SliceModelTypeSchema = z.union([ z.literal(CompositeSliceType), z.literal(SharedSliceType), ]) export type SliceModelType = z.infer