@oberoncms/core
Version:
OberonCMS is a cloud deployable CMS written in typescript based on the Puck visual editor
116 lines (96 loc) • 2.77 kB
text/typescript
import { transformProps, type Data } from "@puckeditor/core"
import { mapConcurrent } from "@tohuhono/utils/map-concurrent"
type PropTransform = Parameters<typeof transformProps>[1]
import type {
OberonConfig,
OberonPage,
OberonPageMeta,
TransformResult,
TransformVersions,
} from "../lib/dtd"
async function applyTransform(
key: string,
transforms: PropTransform,
getPageData: (key: string) => Promise<Data | null>,
updatePageData: (data: OberonPage) => Promise<void>,
): Promise<TransformResult> {
try {
const data = await getPageData(key)
if (!data) {
return {
type: "transform",
key,
status: "success",
}
}
await updatePageData({
key,
data: transformProps(data, transforms),
updatedAt: new Date(),
updatedBy: "migration",
})
return {
type: "transform",
key,
status: "success",
}
} catch (error) {
console.error(error)
return {
type: "transform",
key,
status: "error",
}
}
}
const MAX_CONCURRENCY = 10
export async function* applyTransforms({
transforms,
pages,
getPageData,
updatePageData,
}: {
transforms: PropTransform
pages: OberonPageMeta[]
getPageData: (key: string) => Promise<Data | null>
updatePageData: (data: OberonPage) => Promise<void>
}): AsyncGenerator<TransformResult, void, void> {
yield* mapConcurrent(
pages,
({ key }) => applyTransform(key, transforms, getPageData, updatePageData),
MAX_CONCURRENCY,
)
}
export function getComponentTransformVersions({ components }: OberonConfig) {
const versions: Record<string, number> = {}
for (const key in components) {
const transforms = components[key]?.transforms || []
versions[key] = transforms.length
}
return versions
}
export function getTransforms(
currentTransformVersions: TransformVersions = {},
{ components }: OberonConfig,
) {
const componentTransforms: PropTransform = {}
const transformVersions: TransformVersions = {}
for (const componentKey in components) {
const transforms = components[componentKey]?.transforms || []
const latestTransform = transforms.length
const previousTransform =
currentTransformVersions[componentKey] ?? latestTransform
if (previousTransform < latestTransform) {
componentTransforms[componentKey] = (props: Record<string, unknown>) =>
transforms
.slice(previousTransform)
.reduce((accumulater, transform) => transform(accumulater), props)
}
transformVersions[componentKey] = latestTransform
}
const hasTransforms = !!Object.keys(componentTransforms).length
return {
components: transformVersions,
transforms: hasTransforms && componentTransforms,
}
}