@prismicio/types-internal
Version:
Prismic types for Custom Types and Prismic Data
99 lines (89 loc) • 2.34 kB
text/typescript
import * as t from "io-ts"
import { WidgetKey } from "../common"
import type { Fields } from "../utils"
import {
Group,
NestableWidget,
NestedGroup,
traverseGroup,
traverseSlices,
UID,
} from "./widgets"
import type { SharedSlice } from "./widgets/slices"
import { DynamicWidget, StaticWidget, Widgets } from "./widgets/Widget"
export function sectionReader<T extends StaticWidget | DynamicWidget>(
codec: t.Type<T, unknown>,
) {
return t.record(WidgetKey, codec) // WidgetId -> Widget Data
}
export const StaticSection = sectionReader(StaticWidget)
export type StaticSection = t.TypeOf<typeof StaticSection>
export const DynamicSection = sectionReader(DynamicWidget)
export type DynamicSection = t.TypeOf<typeof DynamicSection>
export const Sections = {
toStatic(
dynamic: DynamicSection,
sharedSlices: Map<string, SharedSlice>,
): StaticSection {
const section = Object.entries(dynamic).reduce(
(
acc: { [key: string]: StaticWidget },
[widgetKey, widget]: [string, DynamicWidget],
) => {
return { ...acc, [widgetKey]: Widgets.toStatic(widget, sharedSlices) }
},
{},
)
return section as StaticSection
},
}
export function traverseSection<
T extends DynamicSection | StaticSection,
>(args: {
path: ReadonlyArray<string>
section: T
onField: Fields.OnFieldFn<UID | NestableWidget | Group | NestedGroup>
}): T {
const { path: prevPath, section: prevSection, onField } = args
let section: T | undefined
for (const [key, prevModel] of Object.entries(prevSection)) {
const path = [...prevPath, key]
let model
switch (prevModel.type) {
case "Choice":
case "Slices":
model = traverseSlices({
path,
slices: prevModel,
onField: onField as Fields.OnFieldFn<
NestableWidget | Group | NestedGroup
>,
})
break
case "Group":
model = onField({
path,
key,
field: traverseGroup({
path,
group: prevModel,
onField: onField as Fields.OnFieldFn<NestableWidget | NestedGroup>,
}),
})
break
default:
model = onField({
path,
key,
field: prevModel,
})
break
}
if (model !== prevModel) {
if (!section) section = { ...prevSection }
section[key] = model
}
}
// returns the traversed model instead of a new one if it didn't change
return section ?? prevSection
}