UNPKG

@prismicio/types-internal

Version:
153 lines (132 loc) 4.16 kB
import * as t from "io-ts" import { withFallback } from "io-ts-types/lib/withFallback" import type { OnFieldFn } from "../../../_internal/utils" import { WidgetKey } from "../../../common" import { Group, NestedGroup, traverseGroup } from "../Group" import { NestableWidget } from "../nestable/NestableWidget" import type { SharedSliceRef } from "./SharedSliceRef" import type { DynamicSlice, StaticSlice } from "./Slice" import { SlicePrimaryWidget } from "./SlicePrimaryWidget" const IMAGE_PLACEHOLDER_URL = "https://images.prismic.io/slice-machine/621a5ec4-0387-4bc5-9860-2dd46cbc07cd_default_ss.png?auto=compress,format" export const Variation = t.exact( t.intersection([ t.type({ id: t.string, name: t.string, description: t.string, imageUrl: withFallback(t.string, IMAGE_PLACEHOLDER_URL), docURL: t.string, version: t.string, }), t.partial({ display: t.string, primary: t.record(WidgetKey, SlicePrimaryWidget), items: t.record(WidgetKey, NestableWidget), }), ]), ) export type Variation = t.TypeOf<typeof Variation> // VariationFields is used exclusively for the slices migration, LegacySlice -> SharedSlice export type VariationFields = { type: "SharedSlice" sliceName: string variationId: string fields: Pick<Variation, "primary" | "items"> } export const SharedSliceType = "SharedSlice" const LegacyPath = t.string const VariationId = t.string export const SharedSlice = t.exact( t.intersection([ t.type({ id: t.string, type: t.literal(SharedSliceType), name: t.string, variations: t.readonlyArray(Variation), }), t.partial({ description: t.string, legacyPaths: t.record(LegacyPath, VariationId), }), ]), ) export type SharedSlice = t.TypeOf<typeof SharedSlice> export function isStaticSharedSlice(slice: StaticSlice): slice is SharedSlice { return slice.type === "SharedSlice" } export function isDynamicSharedSlice( slice: DynamicSlice, ): slice is SharedSliceRef { return slice.type === "SharedSlice" } export function traverseVariation(args: { path: ReadonlyArray<string> variation: Variation onField: OnFieldFn<NestableWidget | Group | NestedGroup> }): Variation { const { path: prevPath, variation, onField } = args let primary: Record<string, NestableWidget | Group> | undefined for (const [key, prevField] of Object.entries(variation.primary ?? {})) { const path = [...prevPath, "primary", key] let field switch (prevField.type) { case "Group": field = traverseGroup({ path, group: prevField, onField: onField as OnFieldFn<NestableWidget | NestedGroup>, }) break default: field = prevField break } const newField = onField({ path, key, field }) if (field !== newField) { if (!primary) primary = { ...variation.primary } primary[key] = newField } } let items: Record<string, NestableWidget> | undefined for (const [key, prevField] of Object.entries(variation.items ?? {})) { const path = [...prevPath, "items", key] const newField = (onField as OnFieldFn<NestableWidget>)({ path, key, field: prevField, }) if (prevField !== newField) { if (!items) items = { ...variation.items } items[key] = newField } } // returns the traversed model instead of a new one if it didn't change return primary || items ? { ...variation, ...(primary && { primary }), ...(items && { items }) } : variation } export function traverseSharedSlice(args: { path: ReadonlyArray<string> slice: SharedSlice onField: OnFieldFn<NestableWidget | Group | NestedGroup> }): SharedSlice { const { path: prevPath, slice, onField } = args let variations: Variation[] | undefined for (let i = 0; i < slice.variations.length; i++) { const variation = slice.variations[i] if (!variation) continue const path = [...prevPath, variation.id] const newVariation = traverseVariation({ path, variation, onField, }) if (newVariation !== variation) { if (!variations) variations = [...slice.variations] variations[i] = newVariation } } // returns the traversed model instead of a new one if it didn't change return variations ? { ...slice, variations } : slice }